Java运算符优先级与赋值

8
我希望有人能够解释以下问题出现的原因,非常感谢。
boolean b = true;
// Compiles OK.
// The LHS "assignment operand" requires no ()parentheses.
if (b=true || b==true);

// Reverse the ||'s operands, and now the code doesn't compile.
if (b==true || b=true);

// Add () around the RHS "assignment operand", and the code now compiles OK.
if (b==true || (b=true));

编辑 -

顺便提一下,代码第二行的编译错误是:"unexpected type",并且出现在短路 OR 运算符所在的位置:

if (b==true || b=true);
//          ^ "unexpected type" compilation error occurs here.

编辑2 -

请注意,本问题中发现的代码片段是“高度人工制造的Java编码”的示例,因此不会出现在专业编写的代码中。

编辑3 -

我是这个非常有用的网站的新手,并且我刚刚学会了如何制作和上传Java编译消息的截图。以下图片复制了我在第一个“编辑”中提供的信息。 它显示了示例代码行#2的编译错误。

Code line #2 compilation error


3
可以增加一个编译错误提示: `if (b==true || b=true); 需要变量, 却发现了一个值` - Eel Lee
谢谢你的建议,我会根据它来编辑我的原始帖子。 - user2911290
1
可能有必要明确一下,这是一种高度人为的“Java运算符测试”类型的问题:我从未见过任何情况需要使用类似这样的结构,即使是这样,将赋值和相等表达式混合在if子句中也是极其不好的风格。(为了完整起见,还可以包括布尔变量b的声明。) - Stuart Rossiter
@monsieurRigsby,感谢您的建议,我已经根据您的建议编辑了我的原始帖子。谢谢。 - user2911290
@user2911290 不错。 - Stuart Rossiter
这个问题似乎不适合讨论,因为它涉及到一个人工示例,而真正的专业程序员不会遇到这种情况。 - Raedwald
3个回答

6
赋值运算符=的优先级低于逻辑或运算符||,因此您可以在赋值中使用逻辑运算符而无需额外添加括号。也就是说,您希望能够编写以下代码:
a = b || c;

不必强制使用 a = (b || c) 的写法。

不幸的是,如果我们只考虑操作符优先级,这个规则也适用于表达式的左侧。 a || b = c 必须解析为

(a || b) = c;

即使你的意图是 a || (b = c)

+1 是为了解释优先级顺序背后的“逻辑”,这与编程有关。 - Stuart Rossiter
在赋值语句的左侧使用运算符的方便之处在于允许使用三元运算符来决定目标(并使解析更容易)。 - ratchet freak
@ratchetfreak,你是指像 p?a:b=c 这样的代码吗?虽然在 C++ 中是有效的,但在 Java 中不是。 - Joni

5

在Java中,赋值运算符的优先级最低。因此,您的前两个表达式相当于:

if ( b = (true || b==true) );

if ( (b==true || b) = true );

第二个表达式无法编译,因为表达式 (b==true || b) 不是左值(即不能被赋值的东西)。

如果添加括号,可以在OR之前进行赋值,这样一切都可以正常工作。


2

使用运算符优先级 (http://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html),我们可以得到以下结果(我添加了括号以表示优先级):

  1. if (b=(true || (b==true)))b 将被赋值为表达式并返回 boolean,因此适合条件;

  2. if (((b==true) || b)=true),左侧不适合于赋值运算符(因为它是表达式而不是变量);

  3. if (((b==true) || (b=true)))booleanOR 进行比较,右侧的 booleanboolean,因为 b 是变量且 = 返回已分配的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接