【问题标题】:String comparison with logical operator in JavaJava中与逻辑运算符的字符串比较
【发布时间】:2011-01-20 08:40:27
【问题描述】:

在比较两个字符串时,有人告诉我不应该使用逻辑运算符 (==)。我们应该使用 String.equals(String) 进行比较。但是,我看到以下代码符合并使用最新的 JDK(1.6_23) 打印“Hello Friend”。我试着四处寻找,找不到任何参考。这是从什么时候开始的?

public class StringComp{
public static void main(String args[]){
        String s = "hello";
        if(s=="hello"){
                System.out.println("Hello Friend");
        }else{
                System.out.println("No Hello");
        }
    }
}

【问题讨论】:

标签: java string-comparison


【解决方案1】:

你不应该使用==,因为它做的事情和你想的不一样。

在这种情况下,“hello”被保存(阅读字符串实习),所以它与您的搅拌是“巧合”。

== 检查两个事物是否完全相同,而不是它们是否具有相同的内容。这是一个非常大的区别,一些偶然的(虽然可以解释)“假阳性”没有理由使用这种方法。

只需使用等号进行字符串比较。

来自这个网站的一个例子: http://blog.enrii.com/2006/03/15/java-string-equality-common-mistake/

String a = new String ("a");
String b = new String ("a");
System.out.println (a == b);

它返回false,而下面的代码返回true。

String a = new String ("a");
String b = new String ("a");
System.out.println (a.equals(b));

【讨论】:

  • 如果添加了“实习”,那是我忘记的词;)
【解决方案2】:

魔法叫做实习

Java interns 字符串字面量,因此它评估为真的可能性很高:

String a = "hello";       // "hello" is assigned *and* interned
String b = "hello";       // b gets a reference to the interned literal
if (a == b)
   System.out.println("internd.");

String c = "hello" + Math.abs(1.0);   // result String is not interned
String d = "hello" + Math.abs(1.0);   // result String is not interned
System.out.println(c==d);             // prints "false"

c = c.intern();
System.out.println(c==d);             // prints "false"

d = d.intern();
System.out.println(c==d);             // prints "true"

【讨论】:

    【解决方案3】:

    == 运算符用于检查两者是否引用同一个 String 对象,而 .equals 比较值。

    【讨论】:

      【解决方案4】:

      它适用于您的情况(AFAIK 在早期的 JVM 中也是如此),因为s 指的是字符串文字"hello"。用字面量初始化的字符串引用指的是字面量(在后台是一个全局对象),而不是单独创建的新对象。正如其他人也提到的那样,这个术语是实习。因此,您的示例中的 s"hello" 指的是同一个物理对象。考虑

      String s1 = "hello";
      String s2 = "hello";
      String s3 = "hello";
      

      所有这些字符串都指向同一个物理对象,因此任何一对字符串之间的“==”比较,或其中任何一个与"hello"之间的比较都会返回true

      然而

      String s4 = new String ("hello");
      

      创建一个新对象,因此s4 == "hello" 产生false

      【讨论】:

      • 感谢您的详细解答。 s2=="hello" 返回真。 s4=="hello" 返回 false,对吗??
      • @Sundeep,是的,这是一个错字,现在已修复 :-)
      【解决方案5】:

      "Java 虚拟机维护一个内部字符串引用列表(唯一字符串池)以避免堆内存中重复的字符串对象。每当 JVM 从类文件加载字符串字面量并执行时,它会检查该字符串是否存在于内部列表与否。如果它已经存在于列表中,那么它不会创建新的字符串,而是使用对现有字符串对象的引用。JVM 在内部对字符串字面量进行这种类型的检查,但不检查它创建的字符串对象通过'new'关键字。您可以显式强制JVM对使用String.intern()方法通过'new'关键字创建的String对象进行这种类型的检查。这会强制JVM检查内部列表并使用现有的String对象如果它已经存在。

      所以结论是,JVM 在内部为字符串字面量维护了唯一的字符串对象。程序员不需要关心字符串字面量,但他们应该关心使用“new”关键字创建的字符串对象,他们应该使用 intern() 方法来避免堆内存中重复的字符串对象,从而提高 java 性能。有关详细信息,请参阅以下部分。”

      参考:PreciseJava.com - Optimization techniques in Strings and StringBuffer (How the JVM works with Strings)

      【讨论】:

      • 感谢您的详细解释。
      【解决方案6】:

      == 比较对象引用

      你可以通过观察下面代码中的输出来理解它:

      public class StringComp{
          public static void main(String args[]){
              String s = new String("hello");
              if(s=="hello"){
                      System.out.println("Hello Friend");
              }else{
                      System.out.println("No Hello");
              }
          }
      }
      

      这个程序会打印No hello

      因为在这段代码中,变量s 引用了新的字符串对象,而该对象又引用了字符串池中的字符串文字“hello”。

      【讨论】:

        【解决方案7】:

        == 比较对象引用,equals() 比较字符串的值。

        在您的情况下,您正在分配两个字符串对象,它们的值都为“hello”,然后将它们与 == 进行比较。编译器可能会决定优化并使用相同的对象引用,从而给出与您得到的结果一样的真实结果。然而,这并不能保证行为 - 使用 equals() 进行值比较更安全。

        【讨论】:

        • “编译器可能决定进行优化” - 这是不准确的。字符串字面量总是被保留。
        猜你喜欢
        • 2018-05-18
        • 1970-01-01
        • 2012-07-16
        • 1970-01-01
        • 2014-04-07
        • 2010-12-24
        • 2021-09-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多