为什么jvm每次使用new关键字创建字符串时都会创建新的字符串Object

时间:2015-09-23 07:11:09

标签: java string string-pool

如果jvm为内存优化创建了string pool,那么为什么每次使用new关键字创建字符串时它都会创建新的对象,即使它存在于string pool中?

7 个答案:

答案 0 :(得分:29)

  

...每当我们使用new关键字创建字符串时,为什么Java会创建新的Object,即使它存在于字符串池中?

因为明确地告诉它! new运算符始终创建一个新对象。 JLS 15.9.4说:

  

"类实例创建表达式的值是对指定类的新创建对象的引用。 每次评估表达式时,都会创建一个新对象。"

为了记录,调用new String(String)几乎总是错误的......但是在不起眼的情况下它可能是有用的。可以想象您可能需要equals返回true==给出false的字符串。致电new String(String)会给你这个。

对于旧版本的Java,substringtrim和可能的其他String方法会为您提供一个与原始文件共享后备存储的字符串。在某些情况下,这可能会导致内存泄漏。例如,调用new String(str.trim())可以防止内存泄漏,但代价是创建修剪后的字符串的新副本。 String(String)构造函数保证分配新的后备数组以及为您提供新的String对象。

{7}中substringtrim的这种行为发生了变化。

答案 1 :(得分:5)

给出原始的声明风格,并为性能设计师引入了String文字。

但是当你使用new关键字时,你就是在堆上显式创建不在常量池中的对象。

当在堆上创建对象时,没有办法彼此共享该内存,并且与常量池不同,它们变得完全陌生。

在堆和常量池String interning之间打破这个障碍会帮助你。

  

string interning是一种只存储每个不同字符串值的一个副本的方法,该字符串值必须是不可变的

请记住,常量池也是堆的一小部分,在可用内存共享的情况下还有一些额外的好处。

答案 2 :(得分:3)

写作时

String str = new String("mystring"); 

然后它就像在你创建的其他对象一样在堆中创建一个字符串对象。字符串文字" mystring"存储在字符串常量池中。

来自Javadocs

  

一个字符串池,最初是空的,由私有维护   class String。

     

当调用实习方法时,如果池已包含   字符串等于此字符串对象由equals(Object)确定   方法,然后返回池中的字符串。否则,这个   String对象被添加到池中以及对此String的引用   返回对象。

     

对于任何两个字符串s和t,s.intern()== t.intern()   当且仅当s.equals(t)为真时才为真。

答案 3 :(得分:1)

要利用字符串池,您需要使用String#intern而不是新的。

答案 4 :(得分:0)

以下对象将存储在String pool:

String s = "hello";

以下对象将存储在Heap中(不在字符串池中):

String s  = new String ("hello")

答案 5 :(得分:0)

强制执行垃圾回收!如果你只需要一次String,那就没有必要将它保存在内存中(对于几乎永远。常量池中的字符串就是这种情况)。不在常量池中的字符串可以像任何其他对象一样进行GC。因此,您应该只在常量池中保留经常使用的字符串(通过使用文字或实习它们)。

答案 6 :(得分:0)

以字符串文字(String s = "string";)的形式创建的字符串存储在字符串池中,但通过使用new(String s = new String("string");调用String构造函数创建的字符串不存储在字符串池中。