java - 关于 '&&' 和 '||' 优先级的混淆示例

标签 java java-7 operator-precedence

我正在测试 && 之间的优先级和 ||我有一个令人困惑的例子。在 Java 中,&&运算符优先级高于运算符 || .

所以如果我们有这 3 个表达式:

//expr1  = true , expr2 = false; expr3 = false;

if(expr1 || expr2 && expr3);

它应该被评估为:

if(expr1 || (expr2 && expr3));

所以 expr2 && expr3应该在 expr1 之前评估.然而,这个例子:

int a1 = 10;
int a2 = 20;
System.out.println(a1 < a2 || ++a1 > a2 && ++a2 < a1);
System.out.println(a1);
System.out.println(a2);

输出:

true
10
20

这证明只有a1 < a2被评估。 您能解释一下为什么会这样吗?

最佳答案

表达式是short-circuiting .来自链接:

when the first argument of the AND function evaluates to false, the overall value must be false; and when the first argument of the OR function evaluates to true, the overall value must be true.

它看到条件的其余部分无关紧要,因为 || 的操作数之一已经为真 (10 < 20)。如果其中一个操作数为真,那么无论其余条件是什么,它都为真。

您可以使用按位 &| 来防止这种情况。


But, the ( expr2 && expr3 ) should be evaluated before expr1, no ?

没有。您必须将优先级评估顺序 的概念分开。

  • 优先级:指示表达式的括号,而不是表达式计算的顺序。例如:

      true || false && false
    

    因为 &&|| 有更高的优先级,所以用括号括起来:

      true || (false && false)
    

    这并不意味着括号中的内容在 Java 的情况下首先被评估。优先级只是阐明运算符的操作数是什么,在本例中为 falsefalse,而在this 中:

      (true || false) && (false || false)
    

    &&的操作数是truefalse,而不是falsefalse.

  • 求值顺序:描述每个操作数的求值顺序和运算符的应用顺序,有时是特定于语言的。与优先级不同,这决定了表达式的计算方式。

在这种情况下,您的示例:

true || false && false

如前所述,由于优先级而变成这样:

true || (false && false)

但 Java 与 C++、JavaScript 或许多其他语言不同,它具有严格的从左到右的计算方式。根据 Java Language Specification :

15.7. Evaluation Order

The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.

15.7.1. Evaluate Left-Hand Operand First

The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.

所以,当你有:

true || (false && false)

Java 首先计算左操作数,结果为 true。然后整个状态短路。括号中 || 的右操作数根本不会被求值。您的另一个示例也是如此:

a1 < a2 || (++a1 > a2 && ++a2 < a1)
           ^^^^^^^^^^^^^^^^^^^^^^^^
           Step 0, precedence and parenthesization

a1 < a2 || (++a1 > a2 && ++a2 < a1)
^^^^^^^
Step 1, left operand evaluated, variables resolved to values 10 and 20, condition is true

true || (++a1 > a2 && ++a2 < a1)
^^^^
Step 2, short circuits, left operand is not evaluated

再举一个更复杂的例子:

false || false || true && (false || true) || false

由于优先级,它变成:

false || false || (true && (false || true)) || false

然后,评估开始,从左到右:

false || false || (true && (false || true)) || false
^^^^^^^^^^^^^^
Step 1, false || false, does not short circuit, right operand is evaluated, is false

false || (true && (false || true)) || false
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Step 2, false || (true && (false || true)), does not short circuit, right operand is evaluated
Step 2A, (true && (false || true)), does not short circuit, right operand is evaluated
Step 2B, (false || true), does not short circuit, right operand is evaluated, is true
Step 2C, (true && true), does not short circuit, right operand is evaluated, is true
Step 2D, false || true, does not short circuit, right operand is evaluated, is true

true || false
^^^^
Step 3, true || false short circuits, right operand is not evaluated, is true

因此整个表达式的计算结果为 true。整个表达式从左到右进行评估。优先级仅通过括号指定运算符的操作数,而不是计算顺序。

进一步阅读 Eric Lippert's explanatory article关于 Daniel Pryden 提到的优先级与关联性与评估顺序,它消除了很多困惑。

主要的收获是优先级并不决定对表达式求值的内容。它只规定了表达式应该如何括起来。另一方面,求值顺序告诉我们表达式是如何求值的,在 Java 中总是从左到右。

关于java - 关于 '&&' 和 '||' 优先级的混淆示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40071805/

相关文章:

java.sql.SQLData - Oracle 对象映射问题

java - 可能的精度损失误差与类型不匹配误差

java - 在单元测试 Struts 2 操作时指定 session /cookies 信息?

java - Android Studio 中“无法解析符号 R”

java - 如何在 java 8 或更高版本编译的 java 7 上运行 Jar

java - 在 Java 8 中使用 LogManager (l4j2) 时出错(无法解析 java.lang.reflect.AnnotatedElement)

c - c结构的&(地址)与->(成员访问)的优先级?

c -++struct.field 中的运算符层次结构

c - 如何理解背靠背运营商的行为?

java - 将方法作为参数传递并在 forEach 循环中使用