关于Java的String pool的问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1881922/
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
Questions about Java's String pool
提问by andandandand
Consider this code:
考虑这个代码:
String first = "abc";
String second = new String("abc");
When using the new
keyword, Java will create the abc
String
again right?
Will this be stored on the regular heap or the String
pool?
How many String
s will end in the String
pool?
当使用new
关键字时,Java 会abc
String
再次创建对吗?这将存储在常规堆或String
池中吗?池中String
将结束多少个s String
?
采纳答案by Jesper
If you use the new
keyword, a new String
object will be created. Note that objects are always on the heap - the string pool is not a separate memory area that is separate from the heap.
如果使用new
关键字,String
将创建一个新对象。请注意,对象始终在堆上——字符串池不是与堆分开的单独内存区域。
The string pool is like a cache. If you do this:
字符串池就像一个缓存。如果你这样做:
String s = "abc";
String p = "abc";
then the Java compiler is smart enough to make just one String
object, and s
and p
will both be referring to that same String object. If you do this:
那么Java编译器是聪明足以让只有一个String
对象,s
并且p
将两者指的是同一个String对象。如果你这样做:
String s = new String("abc");
then there will be one String
object in the pool, the one that represents the literal "abc"
, and there will be a separate String
object, not in the pool, that contains a copy of the content of the pooled object. Since String
is immutable in Java, you're not gaining anything by doing this; calling new String("literal")
never makes sense in Java and is unnecessarily inefficient.
那么String
池中将有一个对象,表示文字的对象"abc"
,并且将有一个单独的String
对象,不在池中,它包含池对象内容的副本。由于String
在 Java 中是不可变的,因此您不会通过这样做获得任何东西;调用new String("literal")
在 Java 中从来没有意义,而且不必要地低效。
Note that you can call intern()
on a String
object. This will put the String
object in the pool if it is not already there, and return the reference to the pooled string. (If it was already in the pool, it just returns a reference to the object that was already there). See the API documentation for that method for more info.
请注意,您可以调用intern()
一个上String
对象。String
如果对象不存在,这会将对象放入池中,并返回对池字符串的引用。(如果它已经在池中,它只返回对已经存在的对象的引用)。有关更多信息,请参阅该方法的 API 文档。
See also String interning(Wikipedia).
另见字符串实习(维基百科)。
回答by dfa
In bytecode, the first assignment is:
在字节码中,第一个赋值是:
Code: 0: ldc #2; //String abc 2: astore_1
whereas the second is:
而第二个是:
3: new #3; //class java/lang/String 6: dup 7: ldc #2; //String abc 9: invokespecial #4; //Method java/lang/String."":(Ljava/lang/String;)V
So the first is in the pool (at position #2) whereas the second will be stored in the heap.
所以第一个在池中(在位置 #2),而第二个将存储在堆中。
EDIT
编辑
Since the CONSTANT_String_info
store the index as U2(16 bits, unsigned) the pool can contain at max 2**16
= 65535
references. In the case you care here more limits of the JVM.
由于将CONSTANT_String_info
索引存储为 U2(16 位,无符号),因此池可以包含 max 2**16
=65535
引用。如果您在这里关心JVM 的更多限制。
回答by loudiyimo
Each time your code create a string literal
每次您的代码创建一个字符串文字时
for example:
例如:
String str="Hello"; (string literal)
the JVM checks the string literal pool first. If the string already exists in the pool, a reference to the pooled instance returns. If the string does not exist in the pool, a new String object instantiates, then is placed in the pool. Java can make this optimization since strings are immutable and can be shared without fear of data corruption
JVM 首先检查字符串文字池。如果该字符串已存在于池中,则返回对池化实例的引用。如果池中不存在该字符串,则实例化一个新的 String 对象,然后将其放入池中。Java 可以进行这种优化,因为字符串是不可变的,并且可以在不担心数据损坏的情况下共享
回答by MeBigFatGuy
The only time you should use new String(foo) is when you want to break ==, which is an odd case, or when foo is a substring of a much larger string that has a limited lifetime, such as
唯一应该使用 new String(foo) 的时候是当你想打破 == 时,这是一个奇怪的情况,或者当 foo 是一个具有有限生命周期的更大字符串的子字符串时,例如
String mystring;
{
String source = getSomeHeinouslyLargeString();
mystring = new String(source.substring(1,3));
}
回答by vimalraj
String strObject = new String("Java");
and
和
String strLiteral = "Java";
Both expression gives you String object, but there is subtle difference between them. When you create String object using new() operator, it always create a new object in heap memory. On the other hand, if you create object using String literal syntax e.g. "Java", it may return an existing object from String pool (a cache of String object in Perm gen space, which is now moved to heap space in recent Java release), if it's already exists.
这两个表达式都为您提供 String 对象,但它们之间存在细微差别。当您使用 new() 运算符创建 String 对象时,它总是在堆内存中创建一个新对象。另一方面,如果您使用字符串文字语法创建对象,例如“Java”,它可能会从字符串池中返回一个现有对象(永久空间中字符串对象的缓存,现在在最近的 Java 版本中移动到堆空间) ,如果它已经存在。
回答by vinsinraw
Though late, may be useful for someone still come across this:
虽然晚了,但可能对仍然遇到此问题的人有用:
String first = "abc";
//One instance object in pool created. Instance variable “first” refers/points to pooled object
String second = new String("abc");
//One instance object in heap created. Object in pool creation step will be skipped on account of first statement.
So in total 2 instance objects will be created. One in pool and other in heap
因此总共将创建 2 个实例对象。一个在池中,另一个在堆中
Detailed Explanation
详细说明
String first = "abc";
String first = "abc";
Here a string object with content "abc" created in pool. The instance variable “first” will point to pool object with content “abc”.
这里在池中创建了一个内容为“abc”的字符串对象。实例变量“first”将指向内容为“abc”的池对象。
String second = new String("abc");
String second = new String("abc");
Here another string object with content "abc" will be created in heap. The instance variable “second” will point to heap object with content “abc”. A string object with content "abc" creation in pool will be skipped on account of 1st statement. Reason below.
这里将在堆中创建另一个内容为“abc”的字符串对象。实例变量“second”将指向内容为“abc”的堆对象。由于第一个语句,池中创建内容为“abc”的字符串对象将被跳过。原因如下。
Reasons
原因
If assumed prior statement (String first = "abc";) is not there with same content, then generally with “new” keyword, 2 string objects will be created one in heap (outside pool) and the other in pool(a subset area of heap). Also the instance variable "second" should point to heap object only, irrespective of whether the objects is in pool or not.
如果假设前面的语句 (String first = "abc";) 不存在相同的内容,那么通常使用“new”关键字,将创建 2 个字符串对象,一个在堆中(池外),另一个在池中(子集区域)堆)。此外,实例变量“second”应该只指向堆对象,而不管对象是否在池中。
Now on account of the presence of prior statement (String first = "abc";) with same content as in new String("abc"), only one object (with content "abc") is retained in pool. So on account of 1st statement, the second statement will have only 1 object created instead of 2 and that object is in heap. Pool object creation will be skipped.
现在,由于存在内容与 new String("abc") 相同的先前语句 (String first = "abc";),池中仅保留一个对象(内容为 "abc")。因此,由于第一个语句,第二个语句将只创建 1 个对象而不是 2 个对象,并且该对象在堆中。将跳过池对象创建。
//Additional Test on the concept
System.out.println(first==second); //returns false. Because first points to pool object while second points to heap object. And both objects are different (on account of different memory locations).
second = second.intern(); //After interning, second now points to pool object. Note: intern is used so that reference variable points to pool area object and not heap object. Clearly it is applicable when we use new keyword.
System.out.println(first==second); //returns true. Because now both first and second objects now points to same pool object.
回答by Kprasanta
String first = "abc";
String second = new String("abc");
In first case there is only one object will create in Pool. In second case two object will create one in pool (if this is not existing previously in Pool) and one in heap.
在第一种情况下,池中只会创建一个对象。在第二种情况下,两个对象将在池中创建一个(如果之前不在池中),一个在堆中。
When you are passing any value with double quote ex: "abc" you are creating a object in pool and passing it to the string constructor for creating a new object with the same value in heap.
当您使用双引号 ex: "abc" 传递任何值时,您正在池中创建一个对象并将其传递给字符串构造函数,以在堆中创建一个具有相同值的新对象。
If you saw the string constructor you can see that it accept a string. What is that string? Before creation what is that string object. It's nothing but an object stored in String Constant pool.
如果您看到字符串构造函数,您可以看到它接受一个字符串。那个字符串是什么?在创建之前,该字符串对象是什么。它只不过是一个存储在字符串常量池中的对象。