Java赋值运算符执行

Sam*_*Sam 74 java string equals assignment-operator

在Java中,我理解赋值求值为右操作数的值,所以像x == (y = x)evaluate 这样的语句true.

但是,此代码输出false.

public static void main(String[]args){
    String x = "hello";
    String y = "goodbye";
    System.out.println(x.equals(x = y));
}
Run Code Online (Sandbox Code Playgroud)

为什么是这样?在我的理解中,它首先评估(x = y),分配xy,然后返回值y.然后x.equals(y)是评估,这应该是true因为xy现在应该共享相同的引用,而是,我得到false.

显示源的屏幕截图以及输出为

这里发生了什么?

Joa*_*uer 74

首先:这是一个有趣的问题,但绝不应该出现在"真正的代码"中,因为即使你知道它是如何工作的,分配你在同一行中调用的变量也会让人感到困惑.

这里发生的是这3个步骤:

  1. 弄清楚调用该方法的对象(即评估第一个x,这将导致对字符串"hello"的引用)
  2. 找出参数(即evaluate x = y,它将更改x为指向String"goodbye"并返回对该String的引用)
  3. equals使用#2的结果作为参数调用#1结果的方法(分别引用字符串"hello"和"goodbye").

查看为该方法生成的字节代码可以清楚地表明(假设您精通Java字节码):

     0: ldc           #2                  // String hello
     2: astore_1
     3: ldc           #3                  // String goodbye
     5: astore_2
     6: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
     9: aload_1
    10: aload_2
    11: dup
    12: astore_1
    13: invokevirtual #5                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
    16: invokevirtual #6                  // Method java/io/PrintStream.println:(Z)V
    19: return
Run Code Online (Sandbox Code Playgroud)

第9行是上面的第1步(即评估x并记住该值).

第10-12行是第2步.它加载y,复制它(一次用于赋值,一次用于赋值表达式的返回值)并将其赋值给x.

第13行调用equals第9行计算的结果和第10-12行的结果.

  • TL;DR:`x.equals(x = y)` => `"hello".equals(x = y)` => `"hello".equals(x = "goodbye")` => `"hello" .equals("goodbye")` => `false`。 (33认同)
  • 需要注意的一点是,[`.`的优先级高于`=`](http://www.cs.bilkent.edu.tr/~guvenir/courses/CS101/op_precedence.html). (7认同)
  • 这更多是关于评估顺序而不是优先级.无论如何,括号使得优先权无关紧要. (3认同)

Ole*_*hov 37

好问题!JLS有答案......

§15.12.4.1(例15.12.4.1-2).方法调用期间的评估顺序:

作为实例方法调用的一部分,有一个表达式,表示要调用的对象.在评估方法调用的任何参数表达式的任何部分之前,此表达式似乎已完全评估.

所以,在:

String x = "hello";
String y = "goodbye";
System.out.println(x.equals(x = y));
Run Code Online (Sandbox Code Playgroud)

在参数表达式x之前.equals首先计算before 的出现次数x = y.

因此,hello  在x更改局部变量以引用字符串之前,将记住对字符串的引用   作为目标引用goodbye.因此,使用参数equals为目标对象调用该方法,因此调用的结果是.hellogoodbyefalse


Kev*_*per 27

重要的是要记住Stringjava中的对象是一个对象,因此是一个引用.你打电话的时候

x.equals(...)
Run Code Online (Sandbox Code Playgroud)

这是检查是否在目前引用的位置的值x等于要传递什么.在里面,你正在改变该值x引用,但你仍然调用equals原来的引用(参考"你好").所以,现在你的代码正在比较,看看"你好"是否等于"再见",这显然不是.在此之后,如果x再次使用,将导致引用与y相同的值.

  • 不,因为(x = y)将返回y的值,即"再见".所以,如果你做了"再见".equals(x = y),那将返回true (3认同)

小智 5

x=y在括号中表示表达式(x=y)现在是goodbye,而外部x in x.equals表示值hello

  • 这实际上并没有解释_why_这种情况正在发生,也没有提供对其他人有帮助的其他细节. (2认同)