String str1="JAVA";
String str2="JAVA";
String str3=new String("JAVA");
String str4=new String("JAVA").intern();
将创建2个对象。 str1
和str2
引用同一个对象,因为字符串文字池概念和str3
指向新对象,因为使用new运算符和str4
指向同一个对象指向{{ 1}}和str1
因为str2
方法检查字符串池中是否有相同值的字符串。
intern()
一个对象将有资格获得GC。这是通过str1=str2=str3=str4=null;
创建的对象。第一个String对象始终可以通过存储在字符串文字池中的引用来访问。
我的解释是否正确?
答案 0 :(得分:12)
在流程中创建的String对象总数?
三:通过文字创建的实习池中的一个以及您通过new String
创建的两个。
一个对象将有资格获得GC。
我在非常的特殊情况下计算两个,甚至可能全部三个:
您在此行中创建的那个:
String str3=new String("JAVA");
(因为您之后将str3
设置为null
)。
您在此行中暂时创建的那个:
String str4=new String("JAVA").intern();
该行创建一个新的String
对象,在其上调用intern
,然后保存对池中字符串的引用。因此理论上,它会创建一个可立即用于GC的String
对象。 (JVM可能足够聪明,不能这样做,但这就是理论。)
最终,在合适的条件下,甚至是实习生池中的字符串。与流行的看法相反,实习池中的字符串可用于垃圾收集,我们可以从the answer to this other question看到。仅仅因为它们属于permgen(unless you're using Oracle's JVM 7 or later)并不意味着它们不是GC,因为the permgen is GC'd too。所以问题就变成了:代码中使用的字符串 literal 何时或如何不再被引用?我不知道答案,但我认为合理的假设将是:何时以及如果使用它的类是从内存中卸载的。根据{{3}},只有在卸载类及其类加载器时才会发生这种情况(即使这样也可能不会发生)。如果类是由系统类加载器加载的(正常情况),那么可能它从未被卸载。
所以几乎可以肯定只有两个(上面的#1和#2),但同时也很有趣地看着#3。