最近在猛学虚拟机(三天打鱼两天晒网),很久之前就想写一篇关于String 中 intern 的帖子了,实在是懒呀懒差点都忘了咋用了,最近又学习了一遍总结如下:

jdk6 中,将这个字符串对象尝试放入串池.

如果串池中有,则并不会放入。只会返回已有的串池中的对象地址

如果没有,则会把对象的复制一份,放入串池,并返回串池中的对象

 

jdk7 起,将这个字符串对象尝试放入串池(jdk8 也是如下方式).

如果串池中有,则并不会放入。只会返回已有的串池中的对象地址

如果没有,则会把对象的引用地址复制一份,放入串池,并返回串池中的引用地址

我们先来看一个例子了解了解:

public class Test {
    public static void main(String[] args) {
        String s = new String("1");
        s.intern();
        String s2 = "1";
        System.out.println(s == s2);

        String s3 = new String("a") + new String("b");
        s3.intern();
        String s4 = "ab";
        System.out.println(s3 == s4);
    }
}

  运行结果如下:

 

 在这里我又不得不提一个东西,那就是单纯的 new String("1") 会对应产生2个文件,一个在堆里面一个在字符串常量池里面。而 使用 new String("a") + new String("b") 时会产生5个对象,其中 new String("a") 和 String("b") 个产生2个对象,“+” 会产生一个 StringBuilder,最后再调用toString () 方法生成一个新对象,我们来看看源码

 

 

会发现这里又new 了一个新对象,而这个新对象只在堆里面有值而在字符串常量池是没有值的。

 

 

 

大家如上所示的图看看这个s 和 s2地址都不一样,自然就返回false 了。首先 执行 new String("1") 时会在堆内和串池中都产生一个值为“1” 的对象。而此时s.intern() 其实对s 本身啥都没做,而 String s2 = "1"; 相当于在堆内产生了新的对象

 

 

 

我来解释下上图,首先s3在堆内new 了一个对象地址为0x002,此后执行了 s3.intern(), 会先去串池里面找一下是否存在 "ab",此时发现不存在.

则会把对象的引用地址复制一份,放入串池,此时串池里面存储的是 "ab" 的地址,而不是对象,而s4 = "ab"; 此时先会去串池里面找“ab”,此时发现已经存在对应的引用,所以返回的就是s3 对象的地址

接下来我们继续看看这个例子:

public class Test {
    public static void main(String[] args) {
        String s3 = new String("a") + new String("b");
        String s5= s3.intern();
        String s4 = "ab";
        System.out.println(s3 == s4);  //true
        System.out.println(s5 == s4);  //true
    }
}

  

 

 这里我特别提及一下s5是咋来的,根据我们上面说的“如果没有,则会把对象的引用地址复制一份,放入串池,并返回串池中的引用地址” ,在执行"s3.intern()"操作后,在这里s5发现在串池中没有字符串"ab" 便将"ab" 在堆中的引用复制一份到串池去,同步返回引用对象的地址,然后s5 同步接收到

接下来我们再看看这个例子:

public class Test {
    public static void main(String[] args) {
        String s3 = new String("a") + new String("b");
        String s5= s3.intern();
        System.out.println(s3 == "ab");
        System.out.println(s5 == "ab");
    }
}

  结果是啥?我给个答案 true true,这里 =="ab",其实和String s4="ab"; ,然后 System.out.println(s3 == s4); 类似

以上是我个人使用jdk8 跑出来的结果,至于jdk6 我是在没有环境就暂时多理解下概念吧~(还是太懒了),后期还会更新的,如有问题麻烦告诉我我们一起多探讨下,我也是个菜逼~