鉴于:
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运算符(||
)的优先级。
答案 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中对此进行了解释。如果第一个布尔表达式分别导致||
或&&
,则true
和false
短路执行。
一元!
的优先级高于按位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
排除了提供的条件中的第一个表达式,因此右手的值无论如何都与左手的值无关。