string - Java赋值运算符执行
在Java中,我理解赋值求值为右操作数的值,因此(x = y)等语句的求值为x。
但是,此代码输出(x = y)。
public static void main(String[]args){
String x = "hello";
String y = "goodbye";
System.out.println(x.equals(x = y));
}
为什么是这样? 在我的理解中,它首先评估(x = y),其中指定x的值为y,然后返回值y.然后评估x.equals(y),这应该是true,因为x和y现在应该共享相同的引用,但相反,我得到false。
这里发生了什么?
9个解决方案
73 votes
首先:这是一个有趣的问题,但绝不应该出现在“真正的代码”中,因为即使你知道它是如何工作的,分配你在同一行中调用的变量也会让人感到困惑。
这里发生的是这3个步骤:
弄清楚调用该方法的对象(即评估第一个equals,这将导致对字符串“hello”的引用)
计算出参数(即评估equals,它将更改x以指向字符串“goodbye”并返回对该字符串的引用)
使用#2的结果作为参数(将分别引用字符串“hello”和“goodbye”)对#1的结果调用方法equals。
查看为该方法生成的字节代码可以清楚地表明(假设您精通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
第9行是上面的第1步(即评估equals并记住该值)。
第10-12行是第2步。它加载equals,复制它(一次用于赋值,一次用于赋值表达式的返回值)并将其赋值给x。
第13行对第9行计算的结果和第10-12行的结果调用equals。
Joachim Sauer answered 2019-05-17T10:35:34Z
36 votes
好问题! JLS有答案......
§15.12.4.1(例15.12.4.1-2)。 方法调用期间的评估顺序:
作为实例方法调用的一部分,有一个表达式 表示要调用的对象。 这个表达似乎是完全的 在方法的任何参数表达式的任何部分之前进行求值 调用被评估。
所以,在:
String x = "hello";
String y = "goodbye";
System.out.println(x.equals(x = y));
在参数表达式goodbye之前,首先计算hello之前hello的出现次数。
因此,在将局部变量x更改为引用字符串goodbye之前,将记住对字符串hello的引用作为目标引用。因此,对于目标对象hello,使用参数goodbye调用equals方法,因此结果为 调用是false。
Oleksandr answered 2019-05-17T10:36:46Z
26 votes
重要的是要记住java中的x是一个对象,因此是一个引用。 你打电话的时候
x.equals(...)
它正在检查当前由x引用的位置的值是否等于您传入的值。在内部,您正在更改x引用的值,但您仍在使用原始引用调用equals(对“hello”的引用“)。 所以,现在你的代码正在比较,看看“你好”是否等于“再见”,这显然不是。 在此之后,如果再次使用x,将导致引用与y相同的值。
Keveloper answered 2019-05-17T10:37:28Z
5 votes
括号中的x=y表示表达式(x=y)现为goodbye,而x.equals中的外部x保存值hello
Chetan Jadhav CD answered 2019-05-17T10:38:01Z
4 votes
Reimus给出了正确的答案,但我想详细说明。
在Java(和大多数语言)中,约定是左边的变量,右边是赋值。
让我们分解一下:
String x = "hello";
//x
String y = "goodbye";
//y
出于调试目的以及代码可读性,将行分开以便它们只做一件事总是一个好习惯。
System.out.println(x.equals(x = y)); //Compound statement
这里,x.equals(...)在x的原始引用上调用,或者“hello”,它被更新为第二个引用。
我会写这个(这会给你你预期的答案):
x = y;
// x
boolean xEqualsX = x.equals(x);
// xEqualsX
System.out.println(xEqualsX);
// "true"
现在看来它应该表现得很明显,但是也很容易看出每一行中到底发生了什么,这是你应该努力的。
Randomness Slayer answered 2019-05-17T10:39:17Z
2 votes
我在eclipse中尝试过你的问题你的两个表达都是正确的。1)x ==(y = x)评估为真这是真的,因为x的值赋予y'hello'然后x和y比较它们同样如此结果也是如此
2)x.equal(x = y)它是假的因为y的值分配给x再见,然后x和x比较它们的值将不同,因此结果将为false
Alishan answered 2019-05-17T10:40:03Z
1 votes
我在外行术语中看到的问题是"hello".equals("goodbye")。所以它返回false。
Vamsi answered 2019-05-17T10:40:38Z
1 votes
在java中String是一个类。
String x = "hello";
String y = "goodbye";
是两个不同的字符串,它引用两个不同的值,它们不相同如果你比较
System.out.println(x.equals(x = y));
//this compare value (hello and goodbye) return true
System.out.println(x == (y = x));
// this compare reference of an object (x and y) return false
Aadesk answered 2019-05-17T10:41:21Z
-4 votes
它看是否x.equals(将x指定为y,始终返回true)所以基本上是x.equals(true)
mmx answered 2019-05-17T10:41:57Z