![](/img/trans.png)
[英]Why are the results of of str == str.intern() for StringBuilder using append or not different?
[英]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);
}
结果:
true
false
第一个打印true
,第二个打印false
。 为什么结果不同?
行为上的差异与StringBuilder
和StringBuffer
之间的差异无关。
String#intern()
的 javadoc 声明它返回
当调用 intern 方法时,如果池中已经包含一个等于该
String
对象的字符串equals(Object)
由equals(Object)
方法确定equals(Object)
,则返回池中的字符串。 否则,将此String
对象添加到池中并返回对此String
对象的引用。
从创建的String
String str2 = new StringBuffer("ja").append("va").toString();
是一个不属于池的全新String
。
为了
str2.intern() == str2
要返回false
, intern()
调用必须返回不同的引用值,即。 String
"java"
已经在池中。
在第一次比较中,在调用intern()
之前, String
“计算机软件”不在字符串池中。 因此intern()
返回的引用与存储在str2
引用相同。 因此引用相等str2 == str2
返回true
。
因为您的作业不会从实习池中重新读取,并且 Java String
(s) 是不可变的。 考虑
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);
输出是(如您所料)
true
true
之前提到了很多关于池的答案,并使用 Oracle 链接文档进行了非常清楚的解释。
我只想指出我们在调试代码时可以检查的方式。
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
您可以使用任何IDE并调试来检查str1和str1.intern()/str2和str2.intern()的实际地址。
让我添加一些更有趣的东西:
所以我认为正确的答案是:
不同供应商的 jvm 或 jvm 版本可能有不同的实现(语言规范不强制如何)
在 Oracle JDK 8 中(我猜你在使用):字符串“java”已经在池中(由 java.lang.Version#laucher_name 加载)并且字符串池只存储引用,而不是对象。
但是在 OpenJDK 中,laucher_name 是“openJDK”;在 Oracle JDK 6 及以下版本中,字符串池会将字符串对象复制到 itslef 中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.