java中的字符串"=="检查引用,为什么这段代码返回true?

HiM*_*ing 6 java

可能重复:
如果==比较Java中的引用,为什么它使用这些字符串评估为true?
与Java中的逻辑运算符进行字符串比较

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

为什么它打印真实?

但,

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

它打印错误.

mic*_*nko 6

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

final String bb = "b";
String b = "a" + bb;
Run Code Online (Sandbox Code Playgroud)

"a" + bb 在编译时进行评估


T.J*_*der 6

你看到两件事结合起来的结果:

  1. 编译器正在处理"a" + bb编译时而不是运行时,因为它bbfinal,所以它知道它可以做到这一点.(还有一些时候它也知道这一点.)

  2. 由编译器生成的所有字符串被拘留.有关实习的更多信息,请参阅另一个关于Java的StackOverflow问题的答案==.

所以结果就是ab指向相同的字符串实例,因此==返回true.


Tho*_*mas 5

Java将实习字符串常量(最终字符串)和文字(在内部池中创建每个字符串的一个实例),因此您可能获得相同的实例,即使它是通过连接"创建"的.

正如其他人已经说过的那样,编译器优化实际上会将连接转换为一个文字("ab").

你永远不能完全依赖==String 的语义,这就是你应该总是使用的原因equals(..).

编辑:澄清上面的句子:

对象==总是意味着比较引用,如果两个引用相同,它将始终返回true.但是,您不能总是依赖于获取对象的相同引用(例如,在您的示例中,简单的final更改行为或在框架中,如Hibernate等) - 这就是您通常应该使用的原因equals(...).

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

另一个==会有不同结果的例子,虽然从一个地方的角度来看都应该是真的:

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
Run Code Online (Sandbox Code Playgroud)

请注意,"最常见"的意思是,这可能会在Java版本(如果不是不同的JVM)之间发生变化,尽管这种情况不太可能发生.

  • *"你永远不能完全依赖于字符串的`==`语义"*当然你可以,就像你可以使用任何其他**引用**类型一样.如果引用指向同一个实例,则`==`将为'true`,如果不引用则为`false`.`equals`完全是另一回事. (2认同)