String.intern()分析
分析代码如下:
String s = new String("1");
s.intern();
String s2 = "1";
System.out.println(s == s2);
String s3 = new String("1") + new String("1");
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);
JDK1.6以及以下:false false
JDK1.7以及以上:false true
在JDK1.6中:
以上代码中,第1行(‘’String s = new String(“1”)‘’),在堆创建对象,并添加入字符串常量池。而第二行.intern(),在JDK1.6中它做了个小动作:检查字符串池里是否存在“1”这么一个字符串。如果存在,就返回池里的字符串;如果不存在,该方法会把”1”添加到字符串池中,然后再返回它的引用。即:先添加,再返回。所以在JDK1.6中始终返回的都是两个不同的地址。然而在JDK1.7中却不是这样。
在JDK1.7中:(由于字符串常量池迁入堆区)
当调用.intern()时,先检查常量池中是否有该字符串的对象,如果有直接返回该字符串对像。如果没有则判断堆上是否有值相等String对象。如果有,则在字符串常量池中生成一个指向堆上对象的地址的引用,从而直接指向堆上的对象。
如上第6行代码中,这行代码在字符串常量池中生成“1” ,并在堆空间中生成s3引用指向的对象(内容为”11”)。注意此时常量池中是没有 “11”对象的。s3.intern(),这一行代码,是将 s3中的“11”字符串放入 String 常量池中,此时常量池中不存在“11”字符串,JDK1.6的做法是直接在常量池中生成一个 “11” 的对象。但是在JDK1.7中,常量池中不需要再存储一份对象了,可以直接存储堆中的引用。这份引用直接指向 s3 引用的对象,也就是说s3.intern() ==s3会返回true。
参考文章:
[ 大神详解 ]