我从一个测验中有一个操作顺序问题,并且说明并没有帮助。这是代码:
package com.udayan.oca;
public class Test {
public static void main(String [] args) {
int a = 2;
boolean res = false;
res = a++ == 2 || --a == 2 && --a == 2;
System.out.println(a);
}
}
它说它会打印出3张,因为我已经测试过了,但是我不知道怎么做。这是他们的解释:
a++ == 2 || --a == 2 && --a == 2;
[给出表达式]。 (a++) == 2 || --a == 2 && --a == 2;
[Postfix的优先级高于其他运算符]。
(a++) == 2 || (--a) == 2 && (--a) == 2;
[在后缀之后,优先级赋予前缀]。
((a++) == 2) || ((--a) == 2) && ((--a) == 2);
[==的优先级高于&&和||]。
((a++) == 2) || (((--a) == 2) && ((--a) == 2));
[&&的优先级高于||]。
让我们开始解决它:((a++) == 2) || (((--a) == 2) && ((--a) == 2));
[a = 2,res = false]。
(2 == 2) || (((--a) == 2) && ((--a) == 2));
[a = 3,res = false]。 true || (((--a) == 2) && ((--a) == 2));
[a = 3,res = false]。
||是短路运算符,因此不需要评估右边的表达式。
res为真,a为3。
是的,我了解短路的情况,因此无需解释。
但是,这是我的想法:
res = a++ == 2 || --a == 2 && --a == 2 ->
(((a++) == 2) || (((--a) == 2) && ((--a) == 2))) [a = 2]
(((a++) == 2) || ((**1** == 2) && ((--a) == 2))) [a = 1]
(((a++) == 2) || (**false** && (**0** == 2))) [a = 1] //short-circuits
(((a++) == 2) || **false**) [a = 1] //short circuits
(**false**) [a = 1]
???? 另一点是答案键说先做a ++,然后||。下一个。是的,是的。但是我认为&&在||之前。
答案 0 :(得分:2)
The conditional-or operator || operator is like | (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is false.
因此,这比您想象的要简单。 res = a++ == 2 || --a == 2 && --a == 2;
的评估方式如下:
res = ((a++ == 2) || ((--a == 2) && (--a == 2)));
a++ == 2
?后递增表示 a 读为 2 。然后对该表达式求值。 2 == 2
,是的。短路意味着该表达式的其余部分从不评估。
因此,基本上上述所有代码都是res = a++ == 2;
我编写了一个简单的程序对此进行测试:
public class TestSOCode {
public static void main(String [] args) {
test1();
}
private static void test1(){
int a = 2;
boolean res = false;
//res = a++ == 2 || --a == 2 && --a == 2;
res = expression(a++, "One") || expression(--a, "Two") && expression(--a, "Three");
System.out.println(res +" "+ a);
}
private static boolean expression(int i, String s){
System.out.println(s+ " called with "+ i);
return i == 2;
}
}
这给出结果
One called with 2
true 3
更新:经过一些讨论和研究,我认为对于逻辑运算符,优先级和执行顺序之间的差异存在误解。
res = a++ == 2 || --a == 2 && --a == 2;
在评估之前,先计算以上语句的优先级。我不会讨论其他优先规则,因为它会使这个答案复杂化,因此我将其简化:
res = x || y && z;
&&
优先,因此将表达式按如下方式分组在一起:
res = x || (y && z);
如我们所见,&&
具有优先权,因此左侧和右侧的表达式组合在一起,然后评估||
。左边的表达式是x
,右边的表达式是(y && z)
(我想我们都认为如果&&
优先,就好像(a || b) && c
一样,将首先进行评估,但这不是它的工作原理)。如果我们希望事实确实如此,则可以像上面这样修改上面的代码:
res = expression(a = 8, "One") || expression(a = 16, "Two") && expression(a = 32, "Three");
这等效于false || (false && false)
,但不会对编译时常数产生任何编译器干扰。结果是:
One called with 8
Two called with 16
false 16
首先评估||
,然后评估&&
的左侧。这将返回false,并且false && ?
将始终为false,因此不会计算第三个表达式。但是没有违反优先级规则。我希望这可以消除任何混乱。如果没有,我很乐意继续在聊天中讨论并更新我的答案。因为我们从原始代码中知道,如果第一个表达式为true,则||
返回true并发生短路,因此可以说a || b && c
没有组合到(a || b) && c
中。>
答案 1 :(得分:0)
最后,当((((a ++)== 2)|| false )[a = 1] 然后做为||运算符的优先级低于++,因此这里a将变为3 ..然后它将打印a = 3 尽管它是短路运算符,但仍然必须首先执行++运算符。