与三元运算符的Java布尔优先级比较

时间:2014-09-02 08:58:21

标签: java boolean comparator operator-precedence

我发现了一个很好的情况,我完全不了解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中也回答了这一点。)

3 个答案:

答案 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