字符串范围:常规堆与池

roc*_*boy 1 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);
}
Run Code Online (Sandbox Code Playgroud)

doSomething2不是更好doSomething1.如果一些字符串的可能性非常低,是否应该鼓励这一点reused.我看到的问题是在案例1中,即使不再使用,字符串也会在延长的时间内保持在范围内.

Ste*_*n C 6

doSomething2比doSomething1更好.

没有.

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

没有.

我看到的问题是在案例1中,即使不再使用,字符串也会在延长的时间内保持在范围内.

我想你误解了这里发生的事情.

String "This string ... returns"是一个String文字,只有在加载包含这些方法的类时,它才会被添加到字符串池中一次.

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

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

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

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


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

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

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