&&
是一个从左到右计算的短路运算符,因此如果&&
运算符左侧的操作数被评估为false,则评估不继续。但我希望在++
之前评估&&
,因为它有higher precedence和(来自链接):
优先级较高的运算符在优先级相对较低的运算符之前进行求值。
在这种情况下,为什么count
在此代码的第三行没有增加?
int mask = 2;
int count = 0;
if( !(mask > 1) && ++count > 1) { mask += 100; }
System.out.println(mask + " " + count);
答案 0 :(得分:6)
不,表达式的计算方式是从左到右,同时考虑运算符优先级。因此,一旦进入a && b
,a
就会变为假,b
将不再评估。
JLS §15.23. Conditional-And Operator &&说:
条件和运算符
&&
类似于&
(第15.22.2节),但仅当其左侧操作数的值为真时才计算其右侧操作数。
以下是对其工作原理的详细分步评估:
这是因为,当您将表达式解析为人类时,首先从最低优先级运算符开始。在这种情况下,&&
的优先级低于++
。
++a < 0 && foo
^^
start
为了计算&&
的结果,您应该知道左操作数:
++a < 0 && ++b
^^^^^^^
so compute this
现在,当您想知道++a < 0
的结果时,请先查看最低优先级运算符,即<
:
++a < 0
^
evaluate this
为了做到这一点,你需要左右操作数。所以计算它们:
++a
0
这是++a
增加的时刻。
所以,现在我们处于最底层。让我们回到顶端:
false && foo
这就是&amp;&amp;&amp;是短路进来。左操作数是假的,因此不再评估右操作数表达式foo
。哪个成了:
false
没有评估右操作数。
答案 1 :(得分:4)
编辑:我错过了问题的重点。有关短路评估的半详细说明,请参见修订版。
逻辑AND和逻辑OR运算符的每个操作数是一个单独的表达式,因此,独立处理(根据正确的运算符优先级给定自己的运算符顺序进行求值)。
因此,虽然++
中++count > 1
的优先级最高,但表达式从未被评估过(因为短路)。
答案 2 :(得分:4)
您似乎对短路评估说明不满意。为什么优先权在这里不重要?
想象一下这段代码:
if( !(mask > 1) && Increment(count) > 1)
函数应用程序(即通过编写括号调用函数)是最高优先级,但函数调用永远不会发生。如果短路评估允许优先考虑,那么它根本不会起作用。
要扩展一点 - ++, - 等运算符都映射到函数调用。但是,编译器需要了解它们绑定的顺序。这不是评估的顺序。
所以a + b * c
并不意味着锻炼b * c然后是总和。这仅表示add( a, multiply(b, c))
评价顺序与&amp;&amp; (虽然不在我的例子中),让程序员更容易编写快速代码。
答案 3 :(得分:1)
为避免混淆,请回忆一下
if (a && b) {
// do something
}
在语义上与:
相同if (a) {
if (b) {
// do something
}
}
显然,如果a
评估为false,则永远不会看到术语b
。特别是,那里的增量opertor将不会执行。
通过回顾这种扩展,行为应该更容易理解。最好将&&
视为上述嵌套if语句的快捷方式。 (如果有else
语句,你还需要添加两个else代码的副本,所以这并不容易。)
更“精确”的表示是使用条件方法:
boolean condition() {
if (!a) return false;
if (!b) return false;
return true;
}
如果b
已经返回false,则永远不会评估a
。
答案 4 :(得分:0)
if(!(mask&gt; 1)&amp;&amp; ++ count&gt; 1){mask + = 100; }
此行表示的是:
!(2>1)
即!(true)
即false
在&&
左侧是假的,它不会进一步检查右侧
所以count
不会增加。