此前我写过另外一篇关于字符串常量池的面试题

运行时常量池的一道面试题(jdk8环境)

本篇博客的内容能证明我上一篇博客中的推论

面试题原题:

public class TestDemo {

    @Test
    public void test01() {
        String str1 = new StringBuilder("ja").append("va").toString();
        String str2 = str1.intern();
        System.out.println(str1 == str2);// 结果是false

        String str3 = new StringBuilder("hello").append("world").toString();
        String str4 = str3.intern();
        System.out.println(str3 == str4);// 结果是true
    }
}

关于String.intern()的正确理解:以str3.intern();为例,如果字符串常量中没有"helloworld"这个字符串,则将这个字符串对象存入字符串常量池中,然后返回这个字符串对象。如果有则直接返回字符串常量池中的对应的那个对象,也就是被str4引用。

关于上面这句话需要注意!

在对象str3的创建到输出true这个过程中,如果按照我的解释:

第一行代码:

String str3 = new StringBuilder(“hello”).append(“world”).toString();

在堆中的Eden区根据已有字符串常量"hello""world"创建一个新的字符串对象"helloworld",此时这个对象只是在堆中的Eden区,而字符串常量池则在堆的Old区。

第二行代码:

String str4 = str3.intern();

str3调用intern方法,因为字符串常量池中没有"helloworld"对象,则将这个对象存入字符串常量池中,然后将这个字符串对象返回。

细节:

很多人在这块没有搞懂,为什么我要这样解释,下面我娓娓道来。

这得涉及到 jvm 的内存管理的知识点。

当我们创建一个对象的时候,意味着需要申请一块空间用来存放这个新创建的对象。可这里有一个问题,jvm 如何管理内存的?