在Java中与逻辑运算符进行字符串比较

问题描述:

比较两个字符串时,我被教导不应该使用逻辑运算符(==)。我们应该使用String.equals(String)进行比较。但是,我发现下面的代码符合并使用最新的JDK(1.6_23)打印“Hello Friend”。我试着四处搜寻,找不到任何参考。从何时发生?在Java中与逻辑运算符进行字符串比较

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"); 
     } 
    } 
} 
+2

http://*.com/questions/767372/java-string-equals-versus – 2011-01-20 08:43:24

+1

另请参阅http://*.com/questions/513832/how-do-i-compare-strings-in-java (接受的答案是指实习) – finnw 2011-01-20 08:53:50

+1

我不认为这是一个骗局。这个问题是问“为什么它有时会工作”而不是“为什么它通常不起作用” – finnw 2011-01-20 08:56:09

您不应该使用==,因为它做了其他的事情,那么你认为。

在这种情况下,“hello”被保存(在字符串实习中读取),所以与您的结果相同的是“巧合”。

==检查两件事情是完全相同的事情,而不是如果他们有相同的内容。这是一个非常大的差异,一些偶然的(虽然可以解释的)“错误的possitives”没有理由使用这种方法。

只需使用等于字符串比较。

从这个网站的例子: 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)); 

==操作者用于检查如果两者都同时.equals比较的值,以相同的字符串对象的引用。

它适用于您的情况(并且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

这个魔术叫做实习

爪哇实习生字符串文字等有其评估为真高概率:

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" 

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

在你的情况你分配两个值为“你好”的字符串对象,然后将它们与==比较。编译器可能会决定优化和使用相同的对象引用,从而得到如你所得到的真实结果。然而这不是保证的行为 - 使用equals()进行值比较要安全得多。

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

因此得出的结论是,JVM在内部为String字面值维护唯一的String对象。程序员不需要关心字符串文字,但是他们应该为使用'new'关键字创建的String对象而烦恼,他们应该使用intern()方法来避免堆内存中重复的String对象,从而提高Java性能。请参阅以下部分以获取更多信息“

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

==比较对象引用

您可以通过观察下面的代码输出明白:

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

因为在此代码中,vari能够s引用新的字符串对象,它反过来引用字符串池中的字符串字符串“hello”。