StringTable
为字符串常量池,是运行时常量池的一部分,一般放String
字符串对象
+ 运算符
两个 " " 相加
String s3="ab";
//["a","b","ab"]
String s4="a"+"b";
System.out.println(s3==s4);//true
s4="a"+"b"
在编译时,会自动优化成"ab"
,查找常量池,如果没有存入,如果有则直接返回该对象
变量相加
String s1="a";
String s2="b";
//["a","b"]
String s3="ab";
String s5=s1+s2;
System.out.println(s3==s5);//false
s5
运行时,调用new StringBuilder().append("a").append("b").toString()
,实际上就是new String("ab")
,创建实例对象,存在java堆
中,而s3
存在常量池中,故不相等
final 变量相加
String s1="a";
final String s2="b";
//["a","b"]
String s3="ab";
String s5="a"+s2;
System.out.println(s3==s5);//true
这里s2
被final
修饰,在编译期就能被识别,然后情况同两个 " " 相加
一样
intern() 方法
// jdk 1.8
String s1="a";
String s2="b";
//["a","b"]
String s5=s1+s2;//new String("ab")
//为堆中对象
String s6=s5.intern();
System.out.println(s5==s6);//true
intern()
方法把对象放入字符串常量池,在jdk1.6和1.8中有不同的特性:
jdk 1.6
:常量池中放入"ab",但 s5 仍为堆对象
jdk 1.8
:常量池中放入"ab",同时 s5也为常量池对象
如果字符串池中已经存在,则直接返回该对象:
// jdk 1.8
String s1="a";
String s2="b";
String s3="ab";
//["a","b","ab"]
String s5=s1+s2;//new String("ab")
//为堆中对象
String s6=s5.intern();
System.out.println(s5==s6);//false
此时s5
不做入池操作,仍为堆对象