1.首先先来看这样一个问题:
String s1 = new String (“test”);
String s2 = new String(“test”);
在这个过程中,创建了几个String对象?
答案是3个:一个test常量在常量池中,两个在堆中,对应的引用分别为s1和s2.
参考:http://blog.youkuaiyun.com/xsf50717/article/details/47339415
2.现在来理解JDK1.7中的intern()方法的工作过程:
String str1 = new StringBuilder(“ja”).append(“av”).toString();
System.out.println(str1 == str1.intern());
String str2 = new StringBuilder(“计算机”).append(“技术”).toString();
System.out.println(str2 == str2.intern());
对于上面的代码,在这里我们使用的是StringBuilder来创建字符串,所以并不会在常量池中创建“java”这个字符串对象和“计算机技术”对象(“java”这个字符串对象本来是存在在常量池的)。所以现在在常量池里面有一个“java”字符串对象,但是没有“计算机技术”这个字符串对象。
在执行str1.intern()这行代码的时候,因为常量池中已经有“java”字符串了,所以直接返回常量池中“java”字符串的引用,而str1返回的是堆中的“java”字符串的引用,所以二者不相等输出false.
在执行str2.intern()这行代码的时候,因为常量池中没有”计算机技术”这个字符串对象,所以会在常量池中记录一个指向堆中”计算机技术”这个字符串的引用,并返回给str2.intern(),也就是说堆中现在保存的是字符串引用了,而不是像JDK1.6中那样,保存的是字符串。所以输入false.
注意:String s1 = new String(“test);
String s2 = new StringBuilder(“test”).toString();
都会在常量池创建“test”常量,而
String s3 = new StringBuilder(“te”).append(“st”).toString();
则不会在常量池创建”test”常量,而会创建”te”和”st”两个常量。
参考:
http://blog.youkuaiyun.com/baidu_31657889/article/details/52315902
http://www.cnblogs.com/wxgblogs/p/5635099.html
《深入理解java虚拟机》周志明 著