在jdk1.7前,new String("Hello")会在推中创建一个"Hello",然后在常量池中创建一个"Hello"。因为jdk1.7前常量池在永久代中,所以比较好理解。
在jdk1.7以及之后,常量池放到堆中了,new String("Hello")在推中创建一个"Hello",在常量池中还会再创建一个"Hello"吗,还是常量池中就放个引用,实际也是指向堆中的"Hello"呢?
如果在常量池中不创建"Hello"的实例而是引用堆中的"Hello"的话,那看下面代码:
String str1 = new String("Hello");
System.out.println(str1.intern() == str1); // false
str1指向推中"Hello",执行str1.intern(),因为常量池中已经有了"Hello"了,所以直接返回的是常量池的地址,而常量池中引用的是堆中的"Hello",那是否是str1.intern()最终返回的也是堆中"Hello"的地址呢,所以str1和str1.intern()地址相等,答案是false,说明分析不正确。
那就说明在常量池中也放了一份"Hello",那都在推中放了两份吗?
所有的字符串字面量(以及一些能在编译期计算出结果的字符串拼接),都会进常量池,参考规范内容
String str1 = new String("Hello");
的"Hello"
在常量池里,str1
是一个新对象str1.intern()
的返回值和"Hello"
是同一个对象str1
还是str1
,所以和"Hello"
不是同一个对象