【问题标题】:a confusion about java String literal pool and String's concatenation关于 java 字符串字面量池和字符串连接的混淆
【发布时间】:2013-03-15 08:18:06
【问题描述】:

所有, 我在写下面的代码时遇到了问题

String hello = "Hello";
String str5 = "Hel" + "lo";
String str8 = "Hel";
String str9 = "lo";
String str10 = str8 + str9;
System.out.println("str10==hello?" + (str10 == hello)); 
System.out.println("str5==hello?" + (str5 == hello));
System.out.println("str10==str5?" + (str10 == str5));

然后我运行我的代码,控制台打印这个

str10 == hello ? false
str5 == hello ? true
str10 == str5 ? false

这让我很困惑。为什么第二个打印 TRUE 但第一个打印 FALSE? 在我对字符串字面量池的理解中,当定义了一个字符串并且 JVM 将检查该池是否包含该字符串,如果没有,则将该字符串放入池中。
在我的代码中,变量 hello 存在在字符串池中,“Helo”和“lo”也在池中,我的问题是

  1. 如果池中存在“Helo”和“lo”的串联结果。
  2. str5和str10s'的定义有什么区别,为什么不是“==”? str5 和 str10 是否引用了字符串池中不同的“Hello”?(“==”似乎表示引用的是同一个对象)

我的jdk版本:1.6.0_29
我的 IDE:Intellij Idea 11.2

谁能指出来?非常感谢

【问题讨论】:

    标签: java string


    【解决方案1】:

    它的行为应该如此。它在 JLS 的两个部分中得到解决。

    JLS #3.10.5:

    作为常量表达式的值的字符串(第 15.28 节) - 使用 String.intern 方法“内部化”以便共享唯一实例。

    JLS #15.28 列出了被视为常量表达式的内容。特别是,字符串字面量是常量表达式(“Hel”和“lo”),但要使变量被视为常量,它必须是最终的。

    在您的情况下,如果您稍微更改代码以使str8str9 保持不变,您将获得true 三倍:

    final String str8 = "Hel";
    final String str9 = "lo";
    

    【讨论】:

      【解决方案2】:
      String hello = "Hello";       // at compile time string is known so in String Constant Pool
      
      String str5 = "Hel" + "lo";   // at compile time string is known so in String Constant Pool same object as in variable hello
      
      String str8 = "Hel";          // at compile time string is known so in String Constant Pool
      
      String str9 = "lo";           // at compile time string is known so in String Constant Pool
      
      String str10 = str8 + str9;   // at runtime don't know values of str8 and str9 so in String Constant Pool new object different from variable hello
      
      str10 == hello ? false        // as str10 has new object and not the same as in hello
      
      str5 == hello ? true          // both were created at compile time so compiler know what's the result in str5 and referenced the same object to str5 as in hello
      
      str10 == str5 ? false         // str10 is a different object, hello and str5 are referenced same object as created at compile time.
      

      【讨论】:

        【解决方案3】:

        代码有以下几点需要考虑:

        String hello = "Hello";
        

        这里的“Hello”是分配给引用 hello 的文字,因此文字有自己的哈希码

        String str5 = "Hel" + "lo";
        

        这里的 "Hel"+"lo" 是 2 个文字组合并分配给引用 hello,因此新文字与第一个文字相同,因此哈希码相同

        String str8 = "Hel";
        String str9 = "lo";
        

        这里 str8 + str9 是 2 个引用,它们组合并指向一个新的引用 hello,因此新的文字有自己的哈希码

        String str10 = str8 + str9;
        System.out.println("str10==hello?" + (str10 == hello)); 
        System.out.println("str5==hello?" + (str5 == hello));
        System.out.println("str10==str5?" + (str10 == str5));
        

        当您使用 == 时,它会按哈希码和值进行匹配。因此不匹配。

        尝试使用

        string_1.equals(string_2)

        而不是

        string_1 ==string_2

        你只会得到值匹配。所以都是真的

        也请参考以下答案(来自What is the difference between == vs equals() in Java?):

        equals() 方法比较 String 实例(在堆上)内的“值”,无论两个(2)对象引用是否引用同一个 String 实例。如果任何两 (2) 个 String 类型的对象引用引用同一个 String 实例,那就太好了!如果两(2)个对象引用引用了两(2)个不同的字符串实例..它没有区别。它是每个被比较的 String 实例中的“值”(即:字符数组的内容)。

        另一方面,“==”运算符比较两个对象引用的值,看它们是否引用同一个 String 实例。如果两个对象的值引用“引用”同一个 String 实例,那么布尔表达式的结果将是“true”..duh。另一方面,如果两个对象引用的值“引用”不同的 String 实例(即使两个 String 实例具有相同的“值”,即每个 String 实例的字符数组的内容相同),则布尔表达式的结果将是“假”。

        【讨论】:

        • 对不起,我不明白“使用 == 它按哈希码和值匹配”,
          我打印 str5、str8、str9、str10 的每个哈希码是 hello.hash- >69609650; str8.hash->72431; str9.hash->3459; str10.hash->69609650; str5.hash->69609650;可以看到,str5、str10的hashcode完全相同,但是str5 == str10返回false;
        • 感谢您花时间写这篇文章。这解决了我在“==”和“等于”之间的混淆。非常感谢
        【解决方案4】:

        如果你比较两个字符串使用string.equals 而不是string1 == string2

        试试看:

        System.out.println("str10==hello?" + (str10.equals(hello));
        

        【讨论】:

        • 是的,我们在String equals源码中可以看到,先判断if (this == anObject) {return true;},然后判断是否是String的实例,如果是,比较两个字符串对象的内容。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-24
        • 1970-01-01
        • 2010-12-26
        • 2018-08-21
        • 2014-09-14
        相关资源
        最近更新 更多