目录
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数组,对外不可见,所以字符串无法被修改
//也没有提供对外的接口
如何修改字符串内容?
- 在运行时通过反射使得String内部的value数组可见,更改数组的值即可(不推荐)
- 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定义类
本文详细介绍了Java中String类的定义、创建方式、字符串比较、常量池原理及手工入池,强调了字符串的不可变性,并探讨了StringBuilder和StringBuffer的使用场景。此外,还讲解了字符串的常见操作如比较、转换、拆分等,以及异常处理的基本概念,包括try-catch-finally语句、throw和throws的用法,最后讨论了异常体系和自定义异常的创建。
486

被折叠的 条评论
为什么被折叠?



