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)
,分配x
值y
,然后返回值y
.然后x.equals(y)
是评估,这应该是true
因为x
和y
现在应该共享相同的引用,而是,我得到false
.
这里发生了什么?
Joa*_*uer 74
首先:这是一个有趣的问题,但绝不应该出现在"真正的代码"中,因为即使你知道它是如何工作的,分配你在同一行中调用的变量也会让人感到困惑.
这里发生的是这3个步骤:
x
,这将导致对字符串"hello"的引用)x = y
,它将更改x
为指向String"goodbye"并返回对该String的引用)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行的结果.
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
为目标对象调用该方法,因此调用的结果是.hello
goodbye
false
Kev*_*per 27
重要的是要记住String
java中的对象是一个对象,因此是一个引用.你打电话的时候
x.equals(...)
Run Code Online (Sandbox Code Playgroud)
这是检查是否在目前引用的位置的值x
等于要传递什么.在里面,你正在改变该值x
被引用,但你仍然调用equals
与原来的引用(参考"你好").所以,现在你的代码正在比较,看看"你好"是否等于"再见",这显然不是.在此之后,如果x
再次使用,将导致引用与y相同的值.
小智 5
x=y
在括号中表示表达式(x=y)
现在是goodbye
,而外部x in x.equals
表示值hello