String对象intern方法的分析和理解

以下测试结果都是在HotSpot JDK1.7中运行的

源码:

public class Intern{
    public static void main(String[] args){
        String str1 = new StringBuilder("计算机").append("系统").toString();
        System.out.println(str1.intern() == str1);
        String str2 = new StringBuilder("In").append("tern").toString();
        System.out.println(str2.intern() == str2);
        String str4 = new StringBuilder("ja").append("va").toString();
        System.out.println(str4.intern() == str4);
        String str3 = new StringBuilder("计算机").append("系统").toString();
        System.out.println(str3.intern() == str3);
        System.out.println(str1.intern() == str3.intern());
    }
}

 

运行结果:

true
false
false
false
true

分析:

1. JDK1.7中,HotSpot已经开始逐步“去永久化”,也就是说对于jvm内存分布中的方法区(即我们常说的常量区)里边的类,对象常量等信息,已经并不一定是永久存在的了,也可能会被GC回收掉

2. JDK1.7中,对String的intern方法做了修改,在1.6及以前的JDK中,intern方法会在调用时先去常量池中查看是否有相同的字符串(equals()),如果有那就返回常量的引用,如果没有就复制字符串实例放到常量区,然后再返回对常量的引用,所以如果用JDK1.6 及以前的版本运行上边代码的话,输出结果都是false。JDK1.7中,intern方法不会再复制实例,而是在常量池中记录首次出现的字符串(equals())的实例引用。在上边的例子中,调用str1.intern()方法时,由于计算机系统String对象是首次出现,此时就会把此对象实例的引用放到常量池中,返回的也是常量池中对首次出现的实例的引用,所以是true。对于Intern和java,由于并不是第一次出现(在加载class文件和执行java命令时已经存储到常量池里),所以输出是false,对于第二次出现的计算机系统,由于不是首次出现,所以是false

3. 对于str1.intern() == str3.intern() 由于返回的都是对首次创建计算机系统字符串实例的引用,所以是true

总结:

1. 1.7JDK中intern()方法始终返回的也是常量池的引用信息,只不过不同的是1.7中返回的是相同字符串(equals())首次创建时的引用地址

2. 常量池中不直接存储字符串常量,而存储的是首次创建此字符串时的引用

posted @ 2016-04-27 22:40  桦沐  阅读(2788)  评论(0编辑  收藏  举报