我发现了一个很好的情况,我完全不了解Java布尔运算符优先级。我知道并验证了oracle官方文档here&&和||优先于三元运算符? :
现在我的代码中有一个类似于
的奇怪行if (a.getItem() != null && a.getItem().getOtherItem() != null?true:a.getItem().getOtherItem().getSomevalue())
{
......
}
我得到的是,a.getItem()中的java.lang.NullPointerException很好.getOtherItem()因为a.getItem()为null。我如何解决它,将其封装在括号
之间if (a.getItem() != null && (a.getItem().getOtherItem() != null?true:a.getItem().getOtherItem().getSomevalue()))
{
......
}
所以我的问题是,如果我按照先前链接的&&amp ;;的官方文档,我会得到一个NullPointerException。优先于?:和&&是短路评估(在questions中也回答了这一点。)
答案 0 :(得分:6)
您似乎对“更高优先级”的含义感到困惑。让我们用一个简单的例子来解释:
运算符*
的优先级高于运算符“+”。这意味着表达式a*b+c
的评估方式与(a*b)+c
类似。这同样适用于&&
运算符和三元运算符:
&&
的优先级高于运算符? :
。这意味着表达式a&&b?c:d
被评估为(a&&b)?c:d
。
因此,运算符优先级的工作原理如您的示例所示。它完全符合您的要求:
if (a.getItem() != null && a.getItem().getOtherItem() != null?
true:a.getItem().getOtherItem().getSomevalue())
如果a.getItem()
不为空且 a.getItem().getOtherItem()
不为空评估为 true ,则 到a.getItem().getOtherItem().getSomevalue()
。因此,当其中任何一个值为null时,代码将尝试评估将产生NullPointerException
的第三个术语。
目前尚不清楚你真正希望实现的目标。在你的第二个例子中,你说:
if (a.getItem() != null && (a.getItem().getOtherItem() != null?
true: a.getItem().getOtherItem().getSomevalue()))
因此,您希望将a.getItem()
null
false
a.getItem().getOtherItem()
解释为null
,但在true
不{{1}的情况下您要求解释案例} a.getItem().getOtherItem()
而null
getSomevalue()
的情况应该导致null
在您刚刚证明的引用上被调用a.getItem().getOtherItem().getSomevalue()
。
如果所有值都不为空,您最有可能想要评估if (a.getItem() != null && a.getItem().getOtherItem() != null?
a.getItem().getOtherItem().getSomevalue(): false)
:
if (a.getItem() != null && a.getItem().getOtherItem() != null
&& a.getItem().getOtherItem().getSomevalue())
请注意,您可以在没有三元运算符的情况下表达相同的内容。等同的陈述是:
true
如果
中的回落值应该是if (a.getItem() != null && a.getItem().getOtherItem() != null?
a.getItem().getOtherItem().getSomevalue(): true)
if (a.getItem() == null || a.getItem().getOtherItem() == null
|| a.getItem().getOtherItem().getSomevalue())
同样可以表示为
true
每当您在复合false
表达式中看到boolean
或{{1}}时,您就可以确定存在错误。
答案 1 :(得分:0)
?
的一般用例是替换简单分配分支中的if
,例如:
int a;
if(isOdd(b) || isPrime(b))
{
a = b;
}
else
{
a = -b;
}
简单地
int a = isOdd(b) || isPrime(b) ? b : -b;
对于此用例,&&
和||
优先于?
是有道理的。
只有当?
返回boolean
时,才会出现混淆,就像你在if
中使用它一样,这在我的经验中非常罕见。
答案 2 :(得分:0)
我在你的if语句中说出来
if (a.getItem() != null && a.getItem().getOtherItem() != null?true:a.getItem().getOtherItem().getSomevalue())
必须首先评估以下最内部部分
null?true:a.getItem().getOtherItem().getSomevalue()
以便将以下部分放在一起
if (a.getItem() != nulla.getItem().getOtherItem() !=<result_from_most_inner_part>)
无论如何,这个if语句很难看。使代码更具可读性,编译器将尽其所能:P