Java的逻辑OR运算符不评估右侧,尽管右侧有一元运算符?

时间:2013-09-02 14:52:52

标签: java operator-precedence unary-operator logical-or

鉴于:

Object x = null;

考虑代码段#1:

if (x == null || !x.equals(new Object()))
    System.out.println("I print!");

代码片段#1没有按照我原先认为的那样抛出NullPointerException。我可以通过|运算符的一些帮助来激发异常。代码段#2:

if (x == null | !x.equals(new Object()))
    System.out.println("This will throw a NullPointerException..");

为什么我的第一个代码片段从未评估过其中包含一元NOT运算符的正确表达式(感叹号!)?根据..所有网站都在那里..一元NOT运算符的优先级高于逻辑OR运算符(||)的优先级。

5 个答案:

答案 0 :(得分:7)

  

一元NOT运算符的优先级高于逻辑OR运算符(||)的优先级。

是的,这是真的。但是,如果在逻辑OR的第一个表达式上使用NOT,则优先级将生效。

考虑条件:

if (!x.equals(y) || y.equals(z))

在这种情况下,否则将首先应用于逻辑OR之前x.equals(y)的结果。因此,如果||的优先级大于!,则表达式将被评估为:

if (!(x.equals(y) || y.equals(z)))

但事实并非如此。如你所知。

但是,如果NOT运算符在第二个表达式上,则优先级不是此处的一个点。第一个表达式将始终在第二个表达式之前首先计算。并且短路行为将发挥作用。

答案 1 :(得分:4)

优先级==评估顺序是一种常见的误解。这并非总是如此。优先级确定编译器构建表达式的顺序,这可以使生成的代码与该顺序匹配,但在某些情况下,例如这是不适用的后增量和短流量算子。

所有优先级均指隐含括号的位置。

if (x == null || !x.equals(new Object()))

相同
if ((x == null) || (!(x.equals(new Object()))))

答案 2 :(得分:0)

this Java tutorial中对此进行了解释。如果第一个布尔表达式分别导致||&&,则truefalse短路执行。

一元!的优先级高于按位OR |。有关优先规则,请参阅here

答案 3 :(得分:0)

short-circuit evaluation上阅读 - 在逻辑OR语句(||)中,仅在第一个参数为false时才评估第二个参数。

使用第二个运算符(bitwise inclusive or|),两个参数都被计算(它不会短路)。因此,因为x为空,第二个将抛出NullPointerException,而第一个则不会。

答案 4 :(得分:0)

如果Java在这方面与C#类似,那么||&&等逻辑运算符将从左到右进行评估。根据定义,如果p == true然后是p OR q == true,那么评估OR的右手是没有意义的。

这可以阻止你做这样的事情(当然,比评估冗余表达式的负载更有效):

if (x != null)
{
    if (x.Property > 0)
    {
        ....
    }
}

我不确定优先级的相关性如何,因为NOT排除了提供的条件中的第一个表达式,因此右手的值无论如何都与左手的值无关。