什么是 Java 字符串池,"s" 与 new String("s") 有何不同?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2486191/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the Java string pool and how is "s" different from new String("s")?
提问by sgokhales
What is meant by String Pool? And what is the difference between the following declarations:
字符串池是什么意思?以下声明之间有什么区别:
String s = "hello";
String s = new String("hello");
Is there any difference between the storing of these two strings by the JVM?
JVM 存储这两个字符串有什么区别吗?
采纳答案by Andrew Hare
The string pool is the JVM's particular implementation of the concept of string interning:
字符串池是 JVM 对字符串实习概念的特定实现:
In computer science, string interning is a method of storing only one copy of each distinct string value, which must be immutable. Interning strings makes some string processing tasks more time- or space-efficient at the cost of requiring more time when the string is created or interned. The distinct values are stored in a string intern pool.
在计算机科学中,字符串实习是一种只存储每个不同字符串值的一个副本的方法,它必须是不可变的。驻留字符串使一些字符串处理任务在时间或空间上更加高效,代价是在创建或驻留字符串时需要更多时间。不同的值存储在字符串实习生池中。
Basically, a string intern pool allows a runtime to save memory by preserving immutable strings in a pool so that areas of the application can reuse instances of common strings instead of creating multiple instances of it.
基本上,字符串实习生池允许运行时通过在池中保留不可变字符串来节省内存,以便应用程序的区域可以重用公共字符串的实例,而不是创建它的多个实例。
As an interesting side note, string interning is an example of the flyweight design pattern:
作为一个有趣的旁注,字符串实习是享元设计模式的一个例子:
Flyweight is a software design pattern. A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects; it is a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory.
Flyweight 是一种软件设计模式。享元是通过与其他类似对象共享尽可能多的数据来最小化内存使用的对象;当简单的重复表示会使用不可接受的内存量时,这是一种使用大量对象的方法。
回答by Chris Dennett
String objects are basically wrappers around string literals. Unique string objects are pooled to prevent unnecessary object creation, and the JVM may decide to pool string literals internally. There is also direct bytecode support for String constants which are referenced multiple times, providing the compiler supports this.
字符串对象基本上是字符串文字的包装器。唯一的字符串对象被池化以防止创建不必要的对象,JVM 可能决定在内部池化字符串文字。对多次引用的字符串常量也有直接的字节码支持,前提是编译器支持这一点。
When you use a literal, say String str = "abc";
, the object in the pool is used. If you use String str = new String("abc");
, a new object is created, but the existing string literal may be reused on either the JVM level or bytecode level (at compile time).
例如,当您使用文字时String str = "abc";
,将使用池中的对象。如果使用String str = new String("abc");
,则会创建一个新对象,但可以在 JVM 级别或字节码级别(在编译时)重用现有的字符串文字。
You can check this for yourself by creating lots of strings in a for loop and using the ==
operator to check for object equality. In the following example, string.value
is private to String
, and holds the string literal used. Because it is private, it has to be accessed via reflection.
您可以通过在 for 循环中创建大量字符串并使用==
运算符检查对象相等性来自己检查这一点。在以下示例中,string.value
是 私有的String
,并保存使用的字符串文字。因为它是私有的,所以必须通过反射来访问它。
public class InternTest {
public static void main(String[] args) {
String rehi = "rehi";
String rehi2 = "rehi";
String rehi2a = "not rehi";
String rehi3 = new String("rehi");
String rehi3a = new String("not rehi");
String rehi4 = new String(rehi);
String rehi5 = new String(rehi2);
String rehi6 = new String(rehi2a);
String[] arr = new String[] { rehi, rehi2, rehi2a, rehi3, rehi3a, rehi4, rehi5, rehi6 };
String[] arr2 = new String[] { "rehi", "rehi (2)", "not rehi", "new String(\"rehi\")", "new String(\"not rehi\")", "new String(rehi)", "new String(rehi (2))", "new String(not rehi)" };
Field f;
try {
f = String.class.getDeclaredField("value");
f.setAccessible(true);
} catch (NoSuchFieldException | SecurityException e) {
throw new IllegalStateException(e);
}
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
System.out.println("i: " +arr2[i]+", j: " +arr2[j]);
System.out.println("i==j: " + (arr[i] == arr[j]));
System.out.println("i equals j: " + (arr[i].equals(arr[j])));
try {
System.out.println("i.value==j.value: " + (f.get(arr[i]) == f.get(arr[j])));
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
System.out.println("========");
}
}
}
}
Output:
输出:
i: rehi, j: rehi
i==j: true
i equals j: true
i.value==j.value: true
========
i: rehi, j: rehi (2)
i==j: true
i equals j: true
i.value==j.value: true
========
i: rehi, j: not rehi
i==j: false
i equals j: false
i.value==j.value: false
========
i: rehi, j: new String("rehi")
i==j: false
i equals j: true
i.value==j.value: true
========
i: rehi, j: new String("not rehi")
i==j: false
i equals j: false
i.value==j.value: false
========
i: rehi, j: new String(rehi)
i==j: false
i equals j: true
i.value==j.value: true
========
i: rehi, j: new String(rehi (2))
i==j: false
i equals j: true
i.value==j.value: true
========
i: rehi, j: new String(not rehi)
i==j: false
i equals j: false
i.value==j.value: false
========
i: rehi (2), j: rehi
i==j: true
i equals j: true
i.value==j.value: true
========
i: rehi (2), j: rehi (2)
i==j: true
i equals j: true
i.value==j.value: true
========
i: rehi (2), j: not rehi
i==j: false
i equals j: false
i.value==j.value: false
========
i: rehi (2), j: new String("rehi")
i==j: false
i equals j: true
i.value==j.value: true
========
i: rehi (2), j: new String("not rehi")
i==j: false
i equals j: false
i.value==j.value: false
========
i: rehi (2), j: new String(rehi)
i==j: false
i equals j: true
i.value==j.value: true
========
i: rehi (2), j: new String(rehi (2))
i==j: false
i equals j: true
i.value==j.value: true
========
i: rehi (2), j: new String(not rehi)
i==j: false
i equals j: false
i.value==j.value: false
========
i: not rehi, j: rehi
i==j: false
i equals j: false
i.value==j.value: false
========
i: not rehi, j: rehi (2)
i==j: false
i equals j: false
i.value==j.value: false
========
i: not rehi, j: not rehi
i==j: true
i equals j: true
i.value==j.value: true
========
i: not rehi, j: new String("rehi")
i==j: false
i equals j: false
i.value==j.value: false
========
i: not rehi, j: new String("not rehi")
i==j: false
i equals j: true
i.value==j.value: true
========
i: not rehi, j: new String(rehi)
i==j: false
i equals j: false
i.value==j.value: false
========
i: not rehi, j: new String(rehi (2))
i==j: false
i equals j: false
i.value==j.value: false
========
i: not rehi, j: new String(not rehi)
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String("rehi"), j: rehi
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String("rehi"), j: rehi (2)
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String("rehi"), j: not rehi
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String("rehi"), j: new String("rehi")
i==j: true
i equals j: true
i.value==j.value: true
========
i: new String("rehi"), j: new String("not rehi")
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String("rehi"), j: new String(rehi)
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String("rehi"), j: new String(rehi (2))
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String("rehi"), j: new String(not rehi)
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String("not rehi"), j: rehi
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String("not rehi"), j: rehi (2)
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String("not rehi"), j: not rehi
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String("not rehi"), j: new String("rehi")
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String("not rehi"), j: new String("not rehi")
i==j: true
i equals j: true
i.value==j.value: true
========
i: new String("not rehi"), j: new String(rehi)
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String("not rehi"), j: new String(rehi (2))
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String("not rehi"), j: new String(not rehi)
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String(rehi), j: rehi
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String(rehi), j: rehi (2)
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String(rehi), j: not rehi
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String(rehi), j: new String("rehi")
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String(rehi), j: new String("not rehi")
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String(rehi), j: new String(rehi)
i==j: true
i equals j: true
i.value==j.value: true
========
i: new String(rehi), j: new String(rehi (2))
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String(rehi), j: new String(not rehi)
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String(rehi (2)), j: rehi
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String(rehi (2)), j: rehi (2)
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String(rehi (2)), j: not rehi
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String(rehi (2)), j: new String("rehi")
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String(rehi (2)), j: new String("not rehi")
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String(rehi (2)), j: new String(rehi)
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String(rehi (2)), j: new String(rehi (2))
i==j: true
i equals j: true
i.value==j.value: true
========
i: new String(rehi (2)), j: new String(not rehi)
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String(not rehi), j: rehi
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String(not rehi), j: rehi (2)
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String(not rehi), j: not rehi
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String(not rehi), j: new String("rehi")
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String(not rehi), j: new String("not rehi")
i==j: false
i equals j: true
i.value==j.value: true
========
i: new String(not rehi), j: new String(rehi)
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String(not rehi), j: new String(rehi (2))
i==j: false
i equals j: false
i.value==j.value: false
========
i: new String(not rehi), j: new String(not rehi)
i==j: true
i equals j: true
i.value==j.value: true
========
回答by Michael Aaron Safyan
The string pool allows string constants to be reused, which is possible because strings in Java are immutable. If you repeat the same string constant all over the place in your Java code, you can actually have only one copy of that string in your system, which is one of the advantages of this mechanism.
字符串池允许重用字符串常量,这是可能的,因为 Java 中的字符串是不可变的。如果您在 Java 代码中到处重复相同的字符串常量,实际上您的系统中只能拥有该字符串的一个副本,这是这种机制的优点之一。
When you use String s = "string constant";
you get the copy that is in the string pool. However, when you do String s = new String("string constant");
you force a copy to be allocated.
当您使用时,您将String s = "string constant";
获得字符串池中的副本。但是,当您这样做时,您会String s = new String("string constant");
强制分配一个副本。
回答by killjoy
Its puzzling that no one directly answered the question but most answers have a lot of upvotes.
令人费解的是,没有人直接回答这个问题,但大多数答案都有很多赞成票。
In a nutshell, the first creates an entry in the String Pool, which can be re-used (more efficient due to above links on immutability, basically, interning), and the second creates a new String object (more costly).
简而言之,第一个在字符串池中创建一个条目,可以重用(由于上述关于不变性的链接效率更高,基本上是实习),第二个创建一个新的 String 对象(成本更高)。
Both objects live in the Heap. The references to both will be in the thread's stack.
这两个对象都存在于堆中。对两者的引用都在线程的堆栈中。
http://www.journaldev.com/797/what-is-java-string-poolgives a clear insight into how this is achieved
http://www.journaldev.com/797/what-is-java-string-pool清楚地了解了这是如何实现的