【问题标题】:Evaluation Respects Parentheses and Precedence - java评估尊重括号和优先级 - java
【发布时间】:2015-07-12 01:56:58
【问题描述】:

根据 Java 语言规范:

评估尊重括号和优先级

除了使用以下数学运算:

int i = 3;
int j =  3 * (9 + 3);
System.out.println(j); //results to 36

还有其他适用此规则的示例吗?我尝试使用

int i = 0;
int z = 0;
if(i++ < 5 || (++z <0 && 5 > z++) || 6 < ++i){
  System.out.println("Routed here");
}
System.out.println("i: " + i);
System.out.println("z: " + z);

但结果是 i:1 和 z:0。看来对那个if例子的评价还是从左到右的。

【问题讨论】:

  • 我知道你不知道短路评估。但我仍然不明白你到底在期待什么,这与评估顺序有什么关系?
  • @sstan 我知道短路是如何工作的,评估是从左到右的,但我很困惑,因为在阅读了 JLS 的那部分后,我认为 Java 在评估时会偏爱括号

标签: java


【解决方案1】:

对于||,Java 在评估表达式时使用短路的概念。因此,在此:

if(i++ < 5 || (++z <0 && 5 > z++) || 6 < ++i){

由于第一个表达式 i++ &lt; 5 返回 true,因此不会计算表达式的其余部分,即从未访问过,因此只会改变 i 的值,而不会带来其他任何东西。

引用自 Java 文档:

条件运算符 && 和 ||运算符对两个布尔表达式执行条件与和条件或运算。这些运算符表现出“短路”行为,这意味着仅在需要时才评估第二个操作数。 && 条件与 ||条件或 以下程序 ConditionalDemo1 测试这些运算符:
class ConditionalDemo1 {

    public static void main(String[] args){
        int value1 = 1;
        int value2 = 2;
        if((value1 == 1) && (value2 == 2))
            System.out.println("value1 is 1 AND value2 is 2");
        if((value1 == 1) || (value2 == 1))
            System.out.println("value1 is 1 OR value2 is 1");
    }
}

【讨论】:

    【解决方案2】:

    括号和优先级与在运行时计算表达式的顺序没有任何关系。也就是说,如果您认为在表达式周围加上括号意味着它会更早地被计算,或者具有更高 precedence 的运算符被更早地计算,那么你就误解了这个概念。

    运算符优先级回答如下问题:在表达式中

    a * b + c
    

    编译器首先将哪个运算符“绑定”到参数?如果+ 具有更高的优先级,它会在* 之前抢到它附近的参数,可以这么说;所以结果是bc相加,结果乘以a。也就是说,它相当于

    a * (b + c)
    

    但在大多数编程语言中(APL 等一些例外情况除外),* 具有更高的优先级。这意味着参数在绑定到+之前绑定到*,这意味着将ab相乘,并将结果添加到c,即

    (a * b) + c
    

    同样,在表达式中

    a + b * c
    

    结果是bc相乘,结果与a相加。

    a + (b * c)
    

    您可以在表达式的某些部分加上括号来更改参数的绑定方式;因此,如果你想将ab 相加并乘以c,你可以说

    (a + b) * c
    

    但非常重要的是要注意:所有这些都控制着如何在编译时解释表达式。 但在运行时,参数总是从左到右计算。 程序运行时,上述所有表达式都会导致程序计算a,然后是b ,然后是c 如果abc 是变量,则无关紧要,但如果它们是方法调用,则可能很重要。在 Java 中,当程序运行时,总是从左到右评估事物。 (这不适用于其他语言;我所知道的大多数语言都让编译器选择顺序。)

    当涉及到||&amp;&amp;(或其他一些语言中的类似运算符)时,再次在运行时,左参数总是首先评估。正确的论点可能会或可能不会被评估。如果您有像 some-expression-1 || some-expression-2 &amp;&amp; some-expression-3 这样的表达式,括号和运算符优先级控制表达式的解释方式,但它们不会在运行时更改计算顺序。

    【讨论】:

      【解决方案3】:

      一旦测试可以被评估为真或假,执行就会跳转到 if 块内。在您的情况下,i 等于 0,它比 5 轻,因此测试评估为 true

      (true OR a OR b) 的值为真,独立于 ab 的值,它们不会被评估(并且不会应用增量)。

      它与(false AND a AND b) 相同,只是它总是会跳过该块。

      检查表达式的顺序,将它们拆分为单独的测试或将增量从测试中取出。以下代码与您的示例等效,但具有您预期的输出:

      int i = 0;
      int z = 1;
      if(i < 5 || (z < 0 && 5 > z+2) || 6 < i+2){
        System.out.println("Routed here");
      }
      i += 2;
      z += 2;
      System.out.println("i: " + i);
      System.out.println("z: " + z);
      

      【讨论】:

        猜你喜欢
        • 2019-10-17
        • 2016-12-31
        • 1970-01-01
        • 1970-01-01
        • 2012-09-19
        • 2011-07-24
        • 2012-08-19
        • 1970-01-01
        • 2019-11-15
        相关资源
        最近更新 更多