2011-09-26 42 views
6

可能重复:
If == compares references in Java, why does it evaluate to true with these Strings?
String comparision with logical operator in Javajava中的字符串“==”检查引用,为什么这段代码返回true?

public static void main(String[] args) 
{ 
    String a = "ab"; 
    final String bb = "b"; 
    String b = "a" + bb; 
    System.out.println(a == b); 
} 

为什么它打印真实?

但是,

public static void main(String[] args) 
{ 
    String a = "ab"; 
    String bb = "b"; 
    String b = "a" + bb; 
    System.out.println(a==b); 
} 

其打印假的。

回答

6

你看到的两件事情结合作用的结果:

  1. 编译器处理"a" + bb在编译时而非运行时,因为bbfinal,因此它知道它可以做那。 (还有一些它也知道。)

  2. 编译器生成的所有字符串都是interned。有关interning的更多信息,请参阅this answer另一个有关==的StackOverflow问题。

所以结果是ab指向相同字符串实例,所以==回报true

6

编译器在编译时计算字符串,因为它是最终的并且永远不会改变。

final String bb = "b"; 
String b = "a" + bb; 

"a" + bb在编译时计算

+0

...这是成功的一半答案... ;-) –

5

Java将实习生字符串常量(最终字符串)和文字(建立在内部池每个字符串的一个实例),因此你可能会得到相同的情况下,即使如果它是通过串联“创建”的。

正如其他人已经指出的那样,编译器优化实际上会将连接转换为一个文字(“ab”)。

你永远无法完全依赖字符串的==语义,这就是为什么你应该总是使用equals(..)

编辑:澄清上面的句子:

随着对象==总是意味着引用进行比较,如果两个引用是相同的,它会永远返回true。然而,你不能总是依赖于获取对象的相同引用(就像在你的示例中,一个简单的final更改行为或者像Hibernate等框架) - 这就是为什么你一般应该使用equals(...)来代替。

当然,如果您需要物理平等(同一个对象)而不是逻辑相等(相同的值),则可以使用==

另一个例子==就会有不同的结果,虽然从一个locical点都应该是真实的:

Integer l1 = 0; 
Integer l2 = 0; 
l1 == l2; //most often true, since Integer objects up to 127 are cached 

Integer l1 = 1000; 
Integer l2 = 1000; 
l1 == l2; //most often false, since those are not cached anymore 

请注意,以“经常”我的意思是,这可能的Java版本之间切换(如果没有不同的JVM),尽管这不太可能。

+2

*“你永远不能完全依赖于字符串的''==语义” *当然可以,就像您可以使用任何其他**参考**类型一样。如果引用指向相同的实例,'=='将是'true';如果不是,则'false'。 “等于”完全是另一回事。 –

+0

@ T.J。我的意思是:你并不总是知道你是否得到了一个字符串的引用,这就是为什么你不能依赖语义。 (这同样适用于'Integer')。 – Thomas

4

的JLS指定此内容的大约String Literals

每个字符串文字是类字符串(§4.3的一个实例(第4.3.1节, §12.5)的参考(§4.3)。 3)。字符串对象具有一个常数值。 使用String.intern方法将字符串文字(或更一般地说是值为 常量表达式(§15.28))的字符串“插入”以便共享唯一的 实例。

因此,由编译单元(第7.3节)的测试程序:

package testPackage; 
class Test { 
    public static void main(String[] args) { 
      String hello = "Hello", lo = "lo"; 
      System.out.print((hello == "Hello") + " "); 
      System.out.print((Other.hello == hello) + " "); 
      System.out.print((other.Other.hello == hello) + " "); 
      System.out.print((hello == ("Hel"+"lo")) + " "); 
      System.out.print((hello == ("Hel"+lo)) + " "); 
      System.out.println(hello == ("Hel"+lo).intern()); 
    } } 

class Other { static String hello = "Hello"; } 

和编译单元:

package other; 
public class Other { static String hello = "Hello"; } 

产生输出:

true true true true false true 

BTW:OMM(jdk1.6.0_21,Ubuntu),上面的代码不包含勒,直到我做other.Other.hellopublic然后将其输出:

true true true true true true 

更新:不,我的错。我的IDE自动将final添加到本地变量声明中。如果我删除,我得到:

true true true true false true 
相关问题