【问题标题】:Logical operator precedence in JavaJava中的逻辑运算符优先级
【发布时间】:2014-02-04 15:54:03
【问题描述】:

我对此不满意:http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.22。它明确指出以下内容:

“如果操作数表达式没有副作用,则每个运算符都是可交换的。”

“这些运算符具有不同的优先级,其中 & 具有最高优先级和 | 最低优先级”。

JVM 为什么不遵守它自己的规则。以下面的例子为例。

public static void main(String[] args){
    boolean bool = isTrue1() | isFalse1() & isFalse2() ;
    System.out.println("Result : " + bool);
}

public static boolean isFalse1() {
    System.out.println("1 : " + false);
    return false ;
}
public static boolean isFalse2() {
    System.out.println("2 : " + false);
    return false ;
}
public static boolean isTrue1() {
    System.out.println("3 : " + true);
    return true ;
}

结果是:

3 : true
1 : false
2 : false
Result : true

虽然实际结果应该是,但根据 & 运算符在 | 之前求值的事实运营商:

1 : false
2 : false
3 : true
Result : true

一些解释会很好解释为什么这没有正确实现。即使在第二部分周围添加括号,也不会使用正确的优先级。

【问题讨论】:

  • 有什么问题?您的结果匹配,它们只是乱序。
  • 这些不是逻辑运算符,而是位运算符。
  • 根据官方java规范,根据周围的数据,它们被称为逻辑运算符和位运算符。同时 && 和 ||被称为条件与/条件或运算符。对于您如何称呼它们的问题,这甚至无关紧要。我建议你看看链接的规范。
  • @trevor-e 问题是,当我的代码有副作用时(我在这里用一个简单的 sout 调用演示了这一点),我不能依赖官方的 java 规范是正确的。我正在寻求解释。
  • @user2890248 “运算符优先级”与表达式的解释方式有关;它只是意味着a | b & c 等价于a | (b & c) 而不是(a | b) & c。它与运行时评估部件的顺序无关。不幸的是,我打算向您指出一个解释“运算符优先级”的资源,但维基百科页面的第一句话实际上混淆了这个问题。我可能不得不抱怨这一点。

标签: java


【解决方案1】:

"这些运算符的优先级不同,其中 & 的优先级最高 优先级和 |最低优先级”。

仅仅因为它们具有更高的优先级,并不意味着它们的操作数将首先被评估。

这个

boolean bool = isTrue1() | isFalse1() & isFalse2() ;

等价于

boolean bool = isTrue1() | ( isFalse1() & isFalse2() ) ;

这就是所有优先级。

正如 Java 语言规范所说,operator operands are evaluated left to right.

Java 编程语言保证 运算符似乎以特定的评估顺序进行评估, 即从左到右。

【讨论】:

    【解决方案2】:

    & 的优先级高于 |但在你的情况下,评估这个:

    boolean bool = isTrue1() | isFalse1() & isFalse2()
    

    与评估此相同:

      boolean bool = (isTrue1()) | (isFalse1() & isFalse2())
    

    也就是说,|的两侧表达式的优先级相同。因此,在这种情况下,java 将按从左到右的顺序评估它们。

    首先它会调用 isTrue1(),它是左边的第一个,然后是第二个括号,再次按照从左到右的顺序评估其中的内容:isFalse1(),然后是 isFalse2()。

    【讨论】:

      【解决方案3】:

      方法评估的顺序不一定与运算符优先级匹配;每个方法的副作用按照您调用该方法的顺序出现,然后评估它们的结果以生成您的最终打印语句。

      【讨论】:

        【解决方案4】:

        您在这里所做的是按位组合,而不是逻辑运算。所以 Java 遵循从左到右的顺序,正如人们所期望的那样。

        如果你实际使用逻辑操作(将|替换为||和&替换为&&),结果变为:

        1 : true
        Result : true
        

        【讨论】:

        • 这不是最重要的区别,重要的是||&&短路
        【解决方案5】:

        Java 将在比较结果之前调用所有函数,因为您使用的是二进制比较器(& 和 |)而不是逻辑比较器(&& 和 ||)

        【讨论】:

        • 如果表达式的结果已经确定,则可能不会调用所有函数 - 这称为short circuit evaluation
        • @Gowtham 短路评估不用于&|。它仅用于&&||
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-08-03
        • 1970-01-01
        • 1970-01-01
        • 2018-12-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多