是什么让引用比较 (==) 对 Java 中的某些字符串起作用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9698260/
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 makes reference comparison (==) work for some strings in Java?
提问by user84592
I have following lines of codes to compare String. str1 not equal to str2, which is understandable since it compares object reference. But then why s1 is equal to s2?
我有以下几行代码来比较字符串。str1 不等于 str2,这是可以理解的,因为它比较对象引用。但是为什么 s1 等于 s2?
String s1 = "abc";
String s2 = "abc";
String str1 = new String("abc");
String str2 = new String("abc");
if (s1==s2)
System.out.println("s1==s2");
else
System.out.println("s1!=s2");
if (str1==str2)
System.out.println("str1==str2");
else
System.out.println("str1!=str2");
if (s1==str1)
System.out.println("str1==s1");
else
System.out.println("str1!=s1");
Output:
输出:
s1==s2
str1!=str2
str1!=s1
采纳答案by Michael Berry
The string constant pool will essentially cache all string literals so they're the same object underneath, which is why you see the output you do for s1==s2
. It's essentially an optimisation in the VM to avoid creating a new string object each time a literal is declared, which could get very expensive very quickly! With your str1==str2
example, you're explicitly telling the VM to create new string objects, hence why it's false.
字符串常量池本质上将缓存所有字符串文字,因此它们在下面是相同的对象,这就是为什么您会看到为s1==s2
. 它本质上是 VM 中的优化,以避免每次声明文字时都创建一个新的字符串对象,这可能会很快变得非常昂贵!在您的str1==str2
示例中,您明确告诉 VM 创建新的字符串对象,因此它是错误的。
As an aside, calling the intern()
method on any string will add it to the constant pool (and return the String that it's added to the pool.) It's not necessarily a good idea to do this however unless you're sure you're dealing with strings that will definitely be used as constants, otherwise you may end up creating hard to track down memory leaks.
顺便说一句,intern()
在任何字符串上调用该方法都会将其添加到常量池中(并返回它添加到池中的字符串。)但是,除非您确定要处理,否则这样做不一定是个好主意肯定会用作常量的字符串,否则最终可能会导致难以追踪内存泄漏。
回答by Chandra Sekhar
s1 and s2 are String literals. When you create a new String literal the compiler first checks whether any literal representing the same is present in the String pool or not. If there is one present, the compiler returns that literal otherwise the compiler creates a new one.
s1 和 s2 是字符串文字。当您创建新的字符串文字时,编译器首先检查字符串池中是否存在任何表示相同文字的文字。如果存在,则编译器返回该文字,否则编译器会创建一个新的。
When you created String s2
the compiler returns the String s1
from the pool as it was already created before. That is the reason why s1
and s2
are same. This behaviour is called interning.
当您创建 String 时s2
,编译器会s1
从池中返回 String ,因为它之前已经创建过。这就是为什么s1
和s2
相同的原因。这种行为称为实习。
回答by zsxwing
In Java, the same constant strings will be reused. So that s1
and s2
point to the same "abc" object and s1==s2
. But when you use new String("abc")
, another object will be created. So that s1 != str1
.
在 Java 中,相同的常量字符串将被重用。所以这s1
并s2
指向同一个“ABC”对象和s1==s2
。但是当您使用 时new String("abc")
,将创建另一个对象。所以那个s1 != str1
。
回答by GETah
This is due to String literals being interned. On this matter, Java documentationssays:
这是由于字符串文字被实习。在这件事上,Java 文档说:
All literal strings and string-valued constant expressions are interned
所有文字字符串和字符串值常量表达式都被实习
And this explains why s1
and s2
are the same (these two variables point to the same interned string)
这解释了为什么s1
和s2
是相同的(这两个变量指向同一个内部字符串)
回答by Bohemian
This phenomenon is due to String interning.
这种现象是由于String实习。
Basically, all string literals are "cached" and reused.
基本上,所有字符串文字都被“缓存”并重用。
回答by Ramesh Papaganti
As
string
is immutable in java, all thestring literals
cached for the reusability.
由于
string
在 java 中是不可变的,所有string literals
缓存都是为了可重用性。
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. Otherwise it will create a new string object and put in string pool for future re-use.
当您使用 new() 运算符创建 String 对象时,它总是在堆内存中创建一个新对象。另一方面,如果您使用字符串字面量语法(例如“Java”)创建对象,它可能会从字符串池中返回一个现有对象(永久空间中的字符串对象缓存,现在在最近的 Java 版本中移动到堆空间) ,如果它已经存在。否则它将创建一个新的字符串对象并放入字符串池中以备将来重用。
String s1 = new String("java");
String s2 = new String("java");
String s3 = "java";
String s4 = "java";