如果jvm
为内存优化创建了string pool
,那么为什么每次使用new
关键字创建字符串时它都会创建新的对象,即使它存在于string pool
中?
答案 0 :(得分:29)
...每当我们使用
new
关键字创建字符串时,为什么Java会创建新的Object,即使它存在于字符串池中?
因为明确地告诉它! new
运算符始终创建一个新对象。 JLS 15.9.4说:
"类实例创建表达式的值是对指定类的新创建对象的引用。 每次评估表达式时,都会创建一个新对象。"
为了记录,调用new String(String)
几乎总是错误的......但是在不起眼的情况下它可能是有用的。可以想象您可能需要equals
返回true
而==
给出false
的字符串。致电new String(String)
会给你这个。
对于旧版本的Java,substring
,trim
和可能的其他String
方法会为您提供一个与原始文件共享后备存储的字符串。在某些情况下,这可能会导致内存泄漏。例如,调用new String(str.trim())
可以防止内存泄漏,但代价是创建修剪后的字符串的新副本。 String(String)
构造函数保证分配新的后备数组以及为您提供新的String
对象。
{7}中substring
和trim
的这种行为发生了变化。
答案 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构造函数创建的字符串不存储在字符串池中。