7
String str1="JAVA";
String str2="JAVA";
String str3=new String("JAVA");
String str4=new String("JAVA").intern();

将创建 2 个对象。str1并且str2由于字符串字面量池的概念而引用相同的对象并str3指向新对象,因为使用新运算符并str4指向相同的对象,str1并且str2因为intern()方法检查到字符串池中是否具有相同的值的字符串。

str1=str2=str3=str4=null;

一个对象将有资格进行 GC。也就是通过创建的对象String str3=new String("JAVA")。第一个 String 对象始终可以通过存储在字符串文字池中的引用进行访问。

我的解释正确吗?

4

1 回答 1

12

进程中创建的字符串对象总数?

三:实习生池中通过文字创建的一个和您通过new String.

一个对象将有资格进行 GC。

在非常特殊的情况下,我数了两个,甚至可能全部三个:

  1. 您在这一行中创建的那个:

    String str3=new String("JAVA");
    

    (因为您后来设置str3null)。

  2. 您在此行中临时创建的那个:

    String str4=new String("JAVA").intern();
    

    该行创建一个新String对象,调用intern它,然后保存对池中字符串的引用。所以理论上,它会创建一个String立即可用于 GC 的对象。(JVM 可能足够聪明,不会那样做,但这就是理论。)

  3. 可能,最终,在适当的条件下,甚至是实习生池中的字符串。与流行的看法相反,实习池中字符串可用于垃圾收集,正如我们从另一个问题的答案中看到的那样。仅仅因为它们在 permgen 中(除非您使用 Oracle 的 JVM 7 或更高版本),这并不意味着它们不是 GC'd,因为permgen 也是 GC'd。所以问题变成了:何时或如何在代码中不再引用字符串文字?我不知道答案,但我认为一个合理的假设是:使用它的类何时以及是否从内存中卸载。根据this other answer,只有当类及其类加载器都被卸载时才会发生(即使那样也可能不会发生)。如果类是由系统类加载器加载的(正常情况),那么它可能永远不会被卸载。

所以几乎可以肯定只有两个(上面的#1和#2),但研究#3也很有趣。

于 2013-06-29T07:17:45.740 回答