简体   繁体   English

为什么这些字符串的 str == str.intern() 结果不同?

[英]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 .行为上的差异与StringBuilderStringBuffer之间的差异无关。

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 the equals(Object) method, then the string from the pool is returned .当调用 intern 方法时,如果池中已经包含一个等于该String对象的字符串equals(Object)equals(Object)方法确定equals(Object) ,则返回池中的字符串 Otherwise, this String object is added to the pool and a reference to this String 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.要返回falseintern()调用必须返回不同的引用值,即。 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:让我添加一些更有趣的东西:

  1. the OpenJDk 8 is true,true; OpenJDK 8 是真的,真的;
  2. Oracle JDK 6 is true,true; Oracle JDK 6 是真的,真的;

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.

相关问题 为什么使用append或者不同的StringBuilder的str == str.intern()的结果? - Why are the results of of str == str.intern() for StringBuilder using append or not different? 为什么String.intern()方法返回两个不同的结果? - Why does the String.intern() method return two different results? 为什么常量字符串使用intern()? - Why constant strings use intern()? 为什么String.intern()在JDK8和JDK9下返回不同的结果? - Why does String.intern() return different results under JDK8 and JDK9? 为什么我使用String.intern()与在Java中传递String对象获得不同的结果? - Why do I get different results with String.intern() vs. passing String object in Java? 给定两个字符串 str1 和 str2 作为输入,删除 str1 中出现在 str2 中的所有字符 - Given two strings, str1 and str2 as input, remove all chars from str1 that appear in str2 为什么`switch(null)`是一个编译错误,但`switch(str)`很好,str是`static final String str = null;`? - Why `switch(null)` is a compile error but `switch(str)` is fine with str being `static final String str = null;`? 为什么以下内容可以确定str1和str2是否为字谜? - Why the following could determine if str1 and str2 are anagram? 实习字符串在不同线程和类交易者之间的行为如何? - How do intern'd strings behave between different threads and classloarders? 在java字符串中使用实习生 - Using intern in java Strings
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM