文章目录
一、String类概览
基础知识
String类被声明为final
,因此它不可被继承。(同样的,Integer
等包装类也不能被继承)
在java8
中,String
内部使用char
数组存储数据。
源代码如下:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
}
在java9
之后,String
类的实现改用byte
数组存储字符串,同时使用coder
来标识使用了哪种编码。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final byte []value;
/** The identifier of the encoding used to encode the bytes in {@code value}. */
private final byte coder;
}
其中,value
数组被声明为final
,这意味着value
数组初始化之后就不能再引用其他数组,并且String
内部没有改变value
数组的方式,因为可以保证String
不可变。
String不可变的好处
1. 可以缓存 hash 值
因为String
的hash
值经常被使用,例如String
用做HashMap
的key
。不可变的特性可以使得hash
值不可变,因此只需要进行一次计算。
2. String Pool 的需要
如果一个String
对象已经被创建过了,那么就会从String Pool
中取得引用。只有String
是不可变的,才可能使用String Pool
。
3. 安全性
String
经常作为参数,String
的不可变性保证了参数不可变。例如,在作为网络连接参数的情况下如果String
是可变的,那么在网络连接过程中,String
被改变,改变String
的那一方以为现在连接的是其它的主机,而实际情况却不一定。
4.线程安全
String
不可变性天生具备线程安全,可以在多个线程中安全的使用。
二、请简述String,StringBuffer,StringBuilder三者之间的共同点与区别,应该分别在何种场景下使用?
共同点:
1、内部实现基于字符数组,封装了对字符串处理的各种操作
2、可自动检测数组越界等运行时异常
不同点
1. 可变性
String内部实现基于常量字符数组,内容不可变;
StringBuffer、StringBuilder基于普通字符数组,数组大小可根据
字符串的实际长度自动扩容,内容可变
2.线程安全
String
不可变,因此是线程安全的StringBuilder
不是线程安全的StringBuffer
是线程安全,内部使用synchronized
进行同步
三者使用场景:
String:对安全要求更高。
StringBuffer、StringBuilder:对性能要求更高。
在实际开发中,95% 的情况使用String,当字符串需要变化时,一般选用StringBuffer。(习惯上的原因,StringBuffer在Java 1.0出现,StringBuilder在Java1.5出发)。
三、String Pool
字符串常量池(String Pool
)保存着所有字符串字面量,这些字面量在编译时期就确定。并且也可以通过 String
的 intern()
方法在运行过程中将字符串添加到String Pool
。
当一个字符串调用intern()
方法时,
-
如果
String Pool
已经存在着一个字符串和该字符串值相等(用equals()
方法进行确定),那么就会返回String Pool
中字符串的引用。 -
否则,就会在
String Pool
添加一个新的字符串,并且返回这个新的字符串的引用。
测试代码如下:
String s1=new String("aaa");
String s2=new String ("aaa");
//false
System.out.println(s1==s2);
String s3= s1.intern();
String s4= s2.intern();
//true
System.out.println(s3==s4);
s1和s2采用的是 new String()
的方式新建了两个不同的字符串,而s3 和s4则是分别通过s1.intern()
与s2.intern()
方法取得的同一个字符串的引用,intern()
首先把aaa
放到String Pool
中,然后返回这个字符串引用,因此s3和s4 引用的是同一个字符串。
如果采用字面量形式创建字符串,那么会自动将字符串放入String Pool
中。
String s5="bbb";
String s6="bbb";