1

我知道字符串池是如何工作的。那说:

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 种情况下,即使不再使用该字符串,它也会在很长一段时间内保持在范围内。

4

3 回答 3

6

doSomething2 是否优于 doSomething1。

不。

鉴于某些字符串被重用的机会非常低,是否应该鼓励这样做。

不。

我看到的问题是在第 1 种情况下,即使不再使用该字符串,它也会在很长一段时间内保持在范围内。

我认为您误解了这里发生的事情。

String是一个字符串字面量,当包含这些方法的类被加载时"This string ... returns",它被添加到字符串池中一次且仅一次。

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

  • doSomething2()方法对存在字符串池的原始字符串进行了新副本。您是正确的,创建的副本doSomething2()不在字符串池中。但是,首先创建副本并没有获得任何有用的结果。你最好只使用原始字符串。

最后,应该注意的是,在加载类时创建的字符串池中的字符串将一直保留在那里,直到类被卸载(如果它被卸载),或者直到应用程序完成。你对此无能为力……而且你也不应该对此做任何事情。

(这种情况类似于 C 或 C++ 中的字符串字面量。AC / C++ 字符串字面量表示为程序初始化常量区域中的字节序列。它会在程序运行期间一直存在,并且有您可以或不应该做任何事情来尝试回收空间。)


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

因为 JVM 不会尝试(并且在一般情况下也不能)确定该常量只会被使用一次。这种分析是困难的,不值得付出努力。

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

于 2013-08-09T04:57:54.370 回答
0

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

String s = new String("Test");

没有将对象放入字符串池中,我们需要调用 String.intern() 方法,该方法用于将对象显式放入字符串池中。只有当您将字符串对象创建为字符串字面量时,例如 String s = "Test" Java 才会自动将其放入字符串池中。

于 2015-11-10T06:33:29.170 回答
-2

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

    String myString="Hello StackOverflow";
    myString.intern();
    if(myString=="Hello StackOverflow")
    System.out.println("Equal");
    else
    System.out.println("Not Equal");
于 2013-08-09T04:45:26.697 回答