【问题标题】:Using "==" in Java [duplicate]在 Java 中使用“==”[重复]
【发布时间】:2020-04-22 19:41:40
【问题描述】:
public class Test { 
    public static void main(String[] args) 
    { 
        String s1 = "HELLO";
        String s2 = "HELLO";

        System.out.println(s1 == s2);  // true
    }  
} 

但是当我使用时:

public class Test { 
    public static void main(String[] args) 
    { 
        String s1 = new String("HELLO");
        String s2 = new String("HELLO");

        System.out.println(s1 == s2); // false
    } 
} 

谁能解释一下这里的区别?谢谢!

【问题讨论】:

标签: java string


【解决方案1】:

在第一个例子中

String s1 = "HELLO";
String s2 = "HELLO";

s1s2 的值是编译时常量。因此,编译器只生成一个String-object,保存值"HELLO",并将其分配给s1s2。这是Common Subexpression Elimination 的一个特例,一种众所周知的编译器优化。因此s1 == s2 返回true

在第二个示例中,两个不同的Strings 是通过new 显式构造的。因此,根据new 的语义,它们必须是单独的对象。

不久前我创建了一个Ideone demo,重点介绍了一些显示这种行为的案例。

您可以使用String::intern() 强制返回相同的String

String s1 = new String("HELLO").intern();
String s2 = new String("HELLO").intern();
System.out.println(s1 == s2); // will print "true";

Ideone demo

【讨论】:

  • 很好的解释,谢谢
【解决方案2】:

如果是字符串字面量,在字符串常量池中创建新对象之前,JVM 将检查是否已在 SCP 区域中存在相同的对象,如果是,它将指向相同的对象而不是创建新的对象。因此,代码如下 s1 = = s2 为真

    String s1 = "HELLO";
    String s2 = "HELLO";

    System.out.println(s1 == s2);  // true

但是我们使用new关键字创建新对象,它会在堆区创建对象,因此s1和s2指向两个不同的对象,因此返回false

【讨论】:

    【解决方案3】:

    == 测试引用相等性(它们是否是同一个对象)。

    .equals() 测试值是否相等(它们在逻辑上是否“相等”)。

    从这里How do I compare strings in Java?

    【讨论】:

    • 这并不能解释为什么第一个例子返回true。
    • 是的!确切地!这就是我困惑的地方
    • String s1 = "HELLO"; String s2 = "HELLO";java如何只为此分配一个对象?
    • 检查该链接的接受答案。
    • 此外,字符串字面量始终指代 String 类的同一个实例。这是因为字符串字面量 - 或者更一般地说,作为常量表达式值的字符串(第 15.28 节) - 是“内部的”,以便使用 String.intern 方法共享唯一实例。 - 从接受的答案再次
    【解决方案4】:

    == 比较对象的引用指针。当 2 个对象是相同的确切对象时,它将是正确的。

    使用双引号实例化字符串使用字符串池,创建一次字符串并重复使用它。

    用 new 实例化一个字符串总是会创建一个全新的字符串。

    【讨论】:

      【解决方案5】:

      == 测试引用相等性(它们是否是同一个对象)。

      第一种情况

      System.out.println(s1 == s2);  // true
      

      因为您正在比较编译器内部的文字,因此引用的是同一个对象。此外,字符串字面量总是引用 String 类的同一个实例。这是因为字符串字面量 - 或者更一般地说,作为常量表达式值的字符串 - 是“内部”的,以便使用 String.intern 方法共享唯一实例。

      第二种情况

      System.out.println(s1 == s2); // false
      

      您正在比较不同的对象引用,因此您得到了错误。

      请查看https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28

      【讨论】:

        【解决方案6】:

        i 第一种情况是 u 比较两个字符串及其 ASCII 值。这就是为什么...//真的 在第二种情况下,您正在比较两个函数/方法。这就是为什么... //假

        【讨论】:

          【解决方案7】:

          第一个是真的,因为 s1 和 s2 在方法区引用了相同的字符串字面量,内存引用是相同的。 ( == 只检查字符串中的引用)。当多次创建相同的字符串文字时,每个不同的字符串值只存储一个副本。 第二个是假的,因为 s1 和 s2 引用堆中的两个不同对象。不同的对象总是有不同的内存引用。

          【讨论】:

            猜你喜欢
            • 2014-12-04
            • 2014-08-15
            • 2011-11-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-06-14
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多