java未赋值 string_string - Java赋值运算符执行

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。

6YH2a.png

这里发生了什么?

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值