[英]Why are the results of of str == str.intern() for these strings different?
public static void main(String[] args) {
String str1 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str1.intern() == str1);
String str2 = new StringBuffer("ja").append("va").toString();
System.out.println(str2.intern() == str2);
}
Results:结果:
true
false
First one prints true
, and the second prints false
.第一个打印
true
,第二个打印false
。 Why are the results different?为什么结果不同?
The difference in behavior is unrelated to the differences between StringBuilder
and StringBuffer
.行为上的差异与
StringBuilder
和StringBuffer
之间的差异无关。
The javadoc of String#intern()
states that it returns String#intern()
的 javadoc 声明它返回
When the intern method is invoked, if the pool already contains a string equal to this
String
object as determined by theequals(Object)
method, then the string from the pool is returned .当调用 intern 方法时,如果池中已经包含一个等于该
String
对象的字符串equals(Object)
由equals(Object)
方法确定equals(Object)
,则返回池中的字符串。 Otherwise, thisString
object is added to the pool and a reference to thisString
object is returned.否则,将此
String
对象添加到池中并返回对此String
对象的引用。
The String
created from从创建的
String
String str2 = new StringBuffer("ja").append("va").toString();
is a brand new String
that does not belong to the pool.是一个不属于池的全新
String
。
For为了
str2.intern() == str2
to return false
, the intern()
call must have returned a different reference value, ie.要返回
false
, intern()
调用必须返回不同的引用值,即。 the String
"java"
was already in the pool . String
"java"
已经在池中。
In the first comparison, the String
"计算机软件" was not in the string pool prior to the call to intern()
.在第一次比较中,在调用
intern()
之前, String
“计算机软件”不在字符串池中。 intern()
therefore returned the same reference as the one stored in str2
.因此
intern()
返回的引用与存储在str2
引用相同。 The reference equality str2 == str2
therefore returns true
.因此引用相等
str2 == str2
返回true
。
Because your assignments don't re-read from the intern pool and Java String
(s) are immutable.因为您的作业不会从实习池中重新读取,并且 Java
String
(s) 是不可变的。 Consider考虑
String str1 = new StringBuilder("计算机").append("软件").toString();
String str1a = new String(str1); // <-- refers to a different String
str1 = str1.intern();
str1a = str1a.intern();
System.out.println(str1a == str1);
String str2 = new StringBuffer("ja").append("va").toString();
String str2a = new String(str2); // <-- refers to a different String
str2 = str2.intern();
str2a = str2a.intern();
System.out.println(str2a == str2);
The output is (as you might expect)输出是(如您所料)
true
true
Lots of answer before mentioned about the pool and explained really clearly with the Oracle link docs.之前提到了很多关于池的答案,并使用 Oracle 链接文档进行了非常清楚的解释。
I just would like to point out the way we can check when debugging code.我只想指出我们在调试代码时可以检查的方式。
String str1 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str1.intern() == str1);//the str1.intern() returns the same memory address the str1
String str2 = new StringBuffer("ja").append("va").toString();
System.out.println(str2.intern() == str2);//the str2.intern() does not return the same memory address the str2
You can use any IDE and debug to check the actual address that the str1 and str1.intern()/str2 and str2.intern().您可以使用任何IDE并调试来检查str1和str1.intern()/str2和str2.intern()的实际地址。
let me add something more interesting:让我添加一些更有趣的东西:
so I think the right answer is :所以我认为正确的答案是:
diffrent vendor's jvm or jvm versions may have diffrent implemention(the language specification don't force the how to)不同供应商的 jvm 或 jvm 版本可能有不同的实现(语言规范不强制如何)
In Oracle JDK 8(I guess u using): String “java” already in pool(loaded by java.lang.Version#laucher_name) and String pool only stores the refrence,not the object.在 Oracle JDK 8 中(我猜你在使用):字符串“java”已经在池中(由 java.lang.Version#laucher_name 加载)并且字符串池只存储引用,而不是对象。
But in OpenJDK the laucher_name is "openJDK";In Oracle JDK 6 and below ,the string pool will copy the string object to itslef .但是在 OpenJDK 中,laucher_name 是“openJDK”;在 Oracle JDK 6 及以下版本中,字符串池会将字符串对象复制到 itslef 中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.