JavaSE_07_String类和异常

本文详细介绍了Java中String类的定义、创建方式、字符串比较、常量池原理及手工入池,强调了字符串的不可变性,并探讨了StringBuilder和StringBuffer的使用场景。此外,还讲解了字符串的常见操作如比较、转换、拆分等,以及异常处理的基本概念,包括try-catch-finally语句、throw和throws的用法,最后讨论了异常体系和自定义异常的创建。

String类的定义

public final class String
    implements  ……

为什么设计成final修饰?

  • 无法被继承,不存在子类。保证所有人使用的String类都是一个版本。
  • 如果存在继承,所有人都可以自定义属于自己版本的String类,String类内部的各种方法也会因为重写产生各种各样的版本,这样String类就没办法作为一个标准在众多用户之间相互使用了!

什么时候用final修饰类?

假设希望当前类不要有别的版本的时候使用final

创建字符串的四种方式

//1
String str1 = "asd";
//2
String str2 = new String("asd");
//3字符数组产生对象
char[] data = new char[]
{'a','s','d'};
String str3 = new String(data);
//4通过String的静态方法ValueOf(任意数据类型),转为字符串
String str4 = String.valueOf(10);

方法一中的直接写出来的"asd"叫做字符串类型的字面量,也叫一个字符串对象

字符串比较

所有引用数据类型的对象比较相等时使用equals()方法(equals()方法位于Object类中),JDK常用类(String、Integer等)都已经在类内部重写了equals()方法,可以直接使用equals()方法比较两个对象是否完全一致。

String str1 = new String("Hello");
String Str2 = new String("hello");
//输出str1.equals(str2),结果为false;
//若要使用不区分大小写的equals(),则使用equalsIgnoreCase()

若使用"==",则比较的是两个对象的地址

String username = null;
//username由用户输入的字符串构成
//若判定输入用户名正确的条件是username为"admin",为了避免在判断输入的用户名正确与否时,使用username.equals()造成的空指针异常,一定要这样写来判定
if("admin".equals(username))

字符串常量池

常量池在堆区

一个JVM进程中,所有常量都是共享的。

String str1 = "hello";    //"hello"常量在常量池中不存在,新建一个字符串对象"hello"将其放入常量池中,str1指向该"hello"对象
String str2 = "hello";    //此时常量池中已存在"hello"常量,不再新建"hello"对象,而是让str2直接指向常量池中对应的"hello"

String str1 = new String("hello");
String str2 = new String("hello");
String str3 = new String("hello");

在这里插入图片描述

常量池设计的依据是共享设计模式,为了节约内存资源。数据库的连接池、线程池都是类似的思想

手工入池
public native String intern();

将当前字符串引用指向的对象保存到字符串常量池中。

  • 若已存在该对象,则不再产生新对象,返回常量池中的String对象;
  • 若池中不存在该对象,则将该对象入池并返回入池后的地址。
String str1 = new String("abc");  //当"abc"一出现,语句从右到左执行,先将"abc"放入常量池中,再在常量池外的普通堆空间内开辟一个String对象,保存"abc"
str1.intern();  //此时常量池中有"abc",str1指向的对象不入池
String str2 = "abc";  //str2指向的对象在常量池中
System.out.println(str1 == str2);
//输出false
char[] data = new char[] {'a','b','c'};
String str1 = new String(data);  //常量池中没有"abc",此时在普通的堆空间中开辟了一个String对象,存储了"abc",str1指向这块空间
str1.intern();  //常量池中没有str1指向的对象中的内容,所以将str1指向的对象移入常量池中
String str2 = "abc";  //常量池中存在"abc",即就是刚才str1指向的对象,此时str2也指向该对象
System.out.println(str1 == str2);
//输出true
字符串不可变性

是指字符串对象的内容不可变,不是对象的引用不可变。只要字符串一经声明,就不可以修改其内部结构。

//String类的内部
private final char[] value; //String字符串在内部是一个value数组,对外不可见,所以字符串无法被修改
//也没有提供对外的接口

如何修改字符串内容?

  1. 在运行时通过反射使得String内部的value数组可见,更改数组的值即可(不推荐)
  2. StringBuilder类、StringBuffer类
  • 若需要频繁修改字符串的内容,使用StringBuilder类的append()方法。

  • StringBuffer使用方法同StringBuilder

  • 因为String类的对象无法修改内容,为了方便字符串的拼接操作,产生了StringBuilder类

  • String和StringBuilder类的相互转换在这里插入图片描述

  • 要反转字符串,将其变为StringBuilder类,调用reverse()方法,再还原为String类

  • StringBuilder类对象的delete(int start, int end)方法:删除两索引区间([start,end))内的值

  • StringBuilder类对象的insert(int start, 任意类型的数据)

  • StringBuilder类对象的reverse(),反转字符串。

StringBuffer是线程安全的操作,性能较差;StringBuilder是线程不安全的操作,性能较高

字符串常见操作

01_字符串比较

equals()

equalsIgnoreCase()

compareTo()返回两字符串ASCII码之差

按照字典序排序:A,ASCII码为65、a,ASCII码为97,A排在a之前。

02_字符和字符串的相互转换

字符串内部就是使用字符数组来存储的

  • char→String

    • String的构造方法传入字符数组

    • 如果通过字符数组对象的toString()方法:因为字符数组类型,没有重写toString()方法,因此输出的是对象地址

    • 通过String.valueOf()

  • String→char

    String str = "abc";
    str.charAt(int index);
    str.toCharArray();
    
03_String和byte[]转换

byte[]–>String

new String(byte[] data);

String–>byte[]

String str = "你好";
byte[] data = str.getBytes();
byte[] data2 = str.getBytes(charsetName:"gbk");
System.out.println(data);
System.out.println(data2);
//UTF8编码(默认编码),将一个汉字编码为3个字节
//gbk编码,将一个汉字转为2字节
04_字符串查找

在这里插入图片描述

05_字符串替换

在这里插入图片描述

06_字符串分割

在这里插入图片描述

拆分IP地址:按照"."拆分

如果split()的regex是特殊字符,需要对其进行转义,这里使用“\\.”

若字符串中没有分割字符,那么仍然返回原字符串

07_字符串截取

在这里插入图片描述

08_其他操作

在这里插入图片描述

isEmpty()不能判断字符串是否为null,只能判断字符串是不是空串
String的方法测试

异常

try {
    //可能会产生异常的代码,除0,数组越界,空指针等
}[catch (可能出现的异常的类型 异常对象的引用)] {  //可以有多个catch块([0,N]),可以捕获0个类型的异常、也可以捕获N个类型的异常。
    //异常的出口,最终会执行的代码块
}
  • 若不处理异常,则发生异常之后的代码就不再执行
  • 处理异常后,try中,发生异常的地方之后的代码不再执行。
  • 所有异常类的父类:Exception

若明确知道try中可能产生的异常类型,catch捕获对应的相关类型;若不清楚会产生哪些异常,catch捕获Exception,所有的异常类都会向上转型变为Exception的引用。

错误“堆栈信息”

输出程序出现异常的位置以及原因

try {
    
} catch (NullPointerException e) {
    e.printStackTrace();
}
finally代码块

无论如何最终都会执行的代码块

若在finally{}中有返回值,则会覆盖前面已经存在的返回值。

finally {
    //资源的释放、方法的关闭
}

无论是否有异常产生,最终都会执行finally代码块中的内容。

异常的执行流程

方法内的异常若没处理,就会抛给方法调用者,若方法嵌套且一直没有遇到异常处理办法,就会一直向上抛,直到从main函数抛给JVM,此时程序停止。

throw和throws的用法

throws:用在方法声明上,表示该方法可能会产生的异常类型,但是本方法中不处理该异常;

throw:用在方法内部,人为产生异常对象并抛出。

异常体系

JDK内部异常的继承关系

在这里插入图片描述

非受查异常

RuntimeException及其子类:数组索引越界、类型转换异常、空指针异常等

Error及其子类(程序内部错误):StackOverFlow, OutOfMemory, Error类体系描述了Java运行系统中的内部错误以及资源耗尽的情形

为非受查异常,编译阶段可以不显示进行异常处理(try catch/throws抛出)

受查异常

除了非受查异常以外的其他异常属于受查异常,必须在编译阶段显示进行异常的处理,否则编译就会出错。比如IOException

自定义异常

若不需要显示进行异常处理,继承RuntimeException定义类

若需要显示进行异常处理,继承Exception定义类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AbyssPraise

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值