字符串范围:常规堆与池

时间:2013-08-09 04:23:28

标签: java string

我知道String pool是如何工作的。那说:

void doSomething1(){
 System.out.println("This string is now added to the string pool and will stay there even after this method returns");
}

void doSomething2(){
 String msg = new String("This string is now added to the string pool and will stay there even after this method returns");

 System.out.println(msg);
}

doSomething2优于doSomething1。如果某些字符串被reused的可能性很小,是否应该鼓励这一点。我看到的问题是在案例1中,即使不再使用该字符串,该字符串也会长时间保留在范围内。

3 个答案:

答案 0 :(得分:6)

  

doSomething2比doSomething1更好。

没有

  

如果某些字符串被重用的可能性很小,是否应该鼓励这一点。

没有

  

我看到的问题是在案例1中,即使不再使用该字符串,该字符串也会在延长期内保留。

我认为你误解了这里发生了什么。

字符串"This string ... returns"是一个字符串文字,当加载包含这些方法的类时,它将被添加到字符串池中一​​次

  • doSomething1()不会向字符串池添加字符串。相反,它使用已存在于字符串池中的现有字符串(我上面提到的字符串)。

  • doSomething2()方法创建了String池中存在的原始String的新副本。你是正确的doSomething2()创建的副本不在字符串池中。但是,通过首先创建副本,您无法实现任何有用的功能。你最好只使用原始字符串。

最后,应该注意的是,在加载类时创建的字符串池中的String将保留在那里,直到卸载类(如果它被卸载),或者直到应用程序完成。关于这一点你无能为力......你应该做什么。

(情况类似于C或C ++中字符串文字所发生的情况.AC / C ++字符串文字表示为程序初始化常量区域中的字节序列。它将在程序运行期间存在,并且没有什么可以或应该做的尝试回收空间。)


  

但是为了理解和完整:这是一个大字符串,只能使用一次,如果我可以保持短范围,为什么把它放在池中?

因为JVM没有尝试(并且在一般情况下不能)确定该常量仅将被使用一次。这种分析很难,而且不值得努力。

对于任何合理大小的字符串文字,不太可能在持续时间内在池中产生任何实际差异。如果字符串文字足够大或数量足以使它确实有所不同,那么它们应该替换为从类路径或其他地方的资源读取的字符串。程序员可以进行此调用...而不是JVM。

答案 1 :(得分:0)

当我们使用new()运算符创建字符串时,它是在堆中创建的,而不是添加到字符串池中,而使用文字创建的字符串是在存在于堆的PermGen区域中的字符串池本身中创建的。

String s = new String(" Test");

不会将对象放在String池中,我们需要调用String.intern()方法,该方法用于将它们显式地放入String池中。它只在你将String对象创建为字符串文字时,例如String s =" Test" Java会自动将其放入String池中。

答案 2 :(得分:-2)

对于Java 7,您可以使用新方法来执行此操作。为方便起见,它会将字符串放入池中。

    String myString="Hello StackOverflow";
    myString.intern();
    if(myString=="Hello StackOverflow")
    System.out.println("Equal");
    else
    System.out.println("Not Equal");