【问题标题】:Using '==' instead of .equals for Java strings [duplicate]对 Java 字符串使用 '==' 而不是 .equals [重复]
【发布时间】:2010-09-11 05:41:40
【问题描述】:

可能重复:
What makes reference comparison (==) work for some strings in Java?

我知道这是asked before,但尽管建议使用.equals() 而不是== 比较运算符,我发现== 一直有效:

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

谁能给我一个 == 运算符失败的例子?

【问题讨论】:

标签: java equals


【解决方案1】:

这是因为你很幸运。 Java 中的== 运算符检查引用相等:如果指针相同,则返回true。它不检查内容是否相等。在编译时找到的相同字符串被折叠成一个 String 实例,因此它适用于 String 文字,但不适用于运行时生成的字符串。

例如,"Foo" == "Foo" 可能有效,但 "Foo" == new String("Foo") 不会,因为 new String("Foo") 创建了一个新的 String 实例,并破坏了任何可能的指针相等性。

更重要的是,大多数 Strings 您在实际程序中处理的都是运行时生成的。文本框中的用户输入是运行时生成的。通过套接字接收的消息是运行时生成的。从文件中读取的内容是运行时生成的。因此,如果要检查内容是否相等,使用 equals 方法而不是 == 运算符非常重要。

【讨论】:

【解决方案2】:

谁能给我一个 == 运算符失败的例子吗?

示例 1:

String s1 = new String("Hello");
String s2 = new String("Hello");
System.out.println(s1 == s2); // false

示例 2:

Integer a=1000,b=1000;
System.out.println(a == b); // false

【讨论】:

  • 猜猜这会起作用。但是字符串不是不可变的吗?因此,他们不应该被拘留吗?
  • 文字字符串被保留。
  • "你好" == "你好" ==> 真的。然而, new String("Hello") 会为一个对象分配一些内存,同样的事情又会在别处为另一个对象分配更多的内存。由于“==”操作符比较引用,它会返回false。
  • 小整数 (-127 .. 127) 也被“拘留”。因此,对于 a = 100,整数示例实际上会返回 true。(这是一个实现细节,但我不想依赖它)。
  • @pessimopoppotamus - only 字符串 literals 会自动被实习。仅当应用程序显式调用 String.intern() 时,其他 String 实例才会被实习。 (这是一个效率问题:实习在很多方面都很昂贵。)
【解决方案3】:

当你这样做时,你实际上是在创建字符串字面量

String s1 = "Hello";
String s2 = "Hello";

编译器找到相同的字符串文字,然后通过在堆中保留一个实例并使堆栈中的所有变量指向它来进行优化。因此,== 将返回 true,因为它们指向相同的内存地址。

当你这样做时,你正在创建字符串对象

String s1 = new String("Hello");
String s2 = new String("Hello");

实例化将在堆上为每一个创建唯一空间,堆栈变量将指向这些单独的位置。因此,使用 .equals() 时它们将相等,因为它们的值相同,但使用 == 时它们将不相等,因为它们是堆内存空间中的不同对象。

【讨论】:

    【解决方案4】:

    经验丰富的 Java 开发人员很少使用 new String(String),但在其他情况下也会出现问题。例如:

    String hello = "Hello"
    String hell = hello.substring(0, 4);
    System.err.println("Hell" == hell);  // should print "false".
    

    (实际应用程序中的大多数 String 实例是通过获取其他 String 的子字符串或从字符数组构造它来形成的。很少有应用程序只会使用作为文字创建的 String 实例。)

    【讨论】:

    • 使用“y = new String(x)”(其中 x 是字符串)的一个原因是允许垃圾收集,此时 x 是一个非常大的字符串的子字符串。如果您只使用“y = x”,那么只要引用了 y,就无法收集非常大的字符串。如果您使用“new String(x)”,则会创建一个不引用原始大字符串的新字符串。
    • 确实如此,但根据我的经验,很少有必要这样做。而如果没有必要,那其实就是反优化。
    猜你喜欢
    • 1970-01-01
    • 2021-07-28
    • 2020-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    相关资源
    最近更新 更多