String(二) 源码分析
以下所有源码都是基于,jdk1.8的版本
String实现的接口
java.io.Serializable
序列化接口可以被序列化与反序列化Comparable<String>
这个接口主要比较大小CharSequence
CharSequence就是字符序列,而String的值是只读序列
String的属性
在Java中String
是一个对象,并不是Java里面的基础数据类型。
private final char value[]:
表示String的由一个final修身的 char value[] 组成的。
private int hash:
表示String对象的hashCode的值,当String创建时栈里面存放的是String的hashCode。
String并没有length属性
String没有length
属性,而是有length()方法,length()方法返回的char数组的长度。
intern()解析
String的 intern()
f查看源码(jdk1.8),对它的描述:
new String(“qwer”).intern()调用时,会先去常量常量池里面查找”qwer”,如果查找到相同”qwer”就不会创建新的”qwer”,而只使用常量池里面的”qwwer”,从而保证这个字符串在常量池里面的唯一性。
下面的一道经典的面试题:
public class StringEqTest {
public static void main(String[] args) {
String s1 = "qwer";
String s2 = "qw";
String s3 = "er";
String s0 = s2+s3;
String s4 = new String("qwer");
String s5 = new String("qwer");
String s6 = new String("qwer").intern();
String s7 = new String("qwer").intern();
System.out.println("s1==s0:\t"+(s1 == s0));
System.out.println("s1==s4:\t"+(s1 == s4));
System.out.println("s4==s5:\t"+(s4==s5));
System.out.println("s5==s6:\t"+(s5==s6));
System.out.println("s1==s6:\t"+(s1==s6));
System.out.println("s6==s7:\t"+(s6==s7));
}
}
来看看结果是不是和你想的一样呢?(这里使用的JDK1.8)
解析:
- s1 == s0 —-> false 这是s0 = s2+s3 这里使用java的重载符号
+
,这反编译过程中+
会调用StringBuild
的append()
方法拼接字符串,最后返回to.String
的结果。所以为false。 - s1 == s4 —-> false s4 的
new
创建了一个新的对象 - s4 == s5 —-> false 分别创建了两个新的对象
- s5 == s6 —-> false 这里要先分析
String().intern()
方法,这个方法在运行时会查找常量池里面是否有”qwer”字符串,若常量池里面有相同的字符串就使用常量池里面的,反之就创建一个新的字符串。s6在常量池里面查找到”qwer”,而s5为new
所有false。 - s1==s6 —–>true ,s6常量池查找到”qwer”,而s1是在常量池里面”qwer”的创建者,所以true。
- s6==s7 ——>true 都是常量池里面的