String常量池
在字符串常量池中生成:
- 直接使用双引号声明
- List item
- 使用intern()方法
位置:
所有字符串都在堆中,和其他普通对象一样。
String拼接
- 常量与常量拼接的结果在常量池,编译期优化
- 常量池中不会存在内容相同的常量
- 只要其中一个是变量,结果就在堆中。变量拼接的源里是StringBuider
- 如果拼接的结果调用intern()方法,则主动将常量池中没有的字符串对象放入池中,并返回此地址
public static void main(String[] args) {
String s1 = "wang";
String s2 = "yongqiang";
String s3 = "wangyongqiang";
String s4 = "wang" + "yongqiang";//编译期优化
//如果拼接中存在变量,则相当于new了一个新的对象
String s5 = s1 + "yongqiang";
String s6 = "wang" + s2;
String s7 = s1 + s2;
/*
String s7 = s1 + s2; 细节
1.StringBuilder s = new StringBurider()
s.append("wang");
s.appeng("yongqiang");
s,toString(); --> 约等于 new String("wangyongqiang")
*/
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//false
System.out.println(s3 == s6);//false
System.out.println(s3 == s7);//false
System.out.println(s5 == s6);//false
System.out.println(s5 == s6);//false
System.out.println(s5 == s7);//false
System.out.println(s6 == s7);//false
//判断字符串常量池中是否存在,如果存在则返回地址,不存在则创建并返回地址
String s8 = s6.intern();
System.out.println(s3 == s8);//true
final String s9 = "wang";
final String s10 = "yongqiang";
String s11 = s9 + s10;
/*
1.字符串拼接操作不一定使用的是StringBuilder,如果字节符号左右两边都是字符串常量或常量引用,则仍然使用编译期优化
2.针对final修饰类、方法、基本数据类型、引用数据类型的量的结构时,能使用的时候建议使用上
*/
System.out.println(s3 == s11);//true
}
intren()方法
-
new String(“ab”) 会生成几个对象
两个,new产生一个对象,“ab”在常量池中产生一个对象 -
new String(“a”)+new String(“b”)生成几个对象,6个
对象1:因为拼接产生一个StringBuilder
对象2:new了一个String
对象3:常量池中的a
对象4:new的String
对象5:常量池中的b深入StringBuilder的toString方法:
对象6:new String(“ab”)
强调:toString()方法没有在字符串常量池中生成”ab“
public static void main(String[] args) {
String s = new String("1");
s.intern();//调用此方法前,常量池中已存在
String s2 = "1";
System.out.println(s == s2);//false
String s3 = new String("1")+new String("1");//s3记录的地址new String("11")的地址,但是常量池中不存在"11"
s3.intern();//在常量池中生成"11"
String s4 = "11";//s4变量的地址是上一行代码执行时在常量池中生成的"11"的地址
//关键是String常量池的位置和toString()方法
System.out.println(s3 == s4);//jdk6:false jdk7/8:true
}