Java在“&&”(和)运算符中即使其中一个参数为false也会检查所有参数吗?

14

我有这样一段代码:

if(object != null && object.field != null){
    object.field = "foo";
}

假设对象为null。

这段代码会导致nullPointerException还是if语句不会被执行?

如果会,如何重构这段代码使其更加优雅(如果可能的话)?


3
玩转:http://ideone.com/KRMwj - zengr
另一个案例:http://ideone.com/NAP0Q - zengr
10个回答

19

&&在短路的时候会停止计算,而&则不会。

但对于像这样简单的问题,最好还是自己试一下(当你没有机器可以使用时,ideone可以提供帮助)。

&& - http://ideone.com/LvV6w & - http://ideone.com/X5PdU

最后,确认答案的最佳途径是参考JLS §15.23。尽管不太容易阅读,但相关章节说明如下: &&运算符类似于&(§15.22.2),但只有左操作数的值为true时才计算右操作数的值。


10

Java具有短路运算,即您的代码应该没问题。


Java有短路运算,没错,但这个例子中只使用了&&而不是&。如果用&,会导致空指针异常。 - Captain Man
“&&和&的区别”?你在问题中哪里看到了这个? - Alexander Farber
1
我只是加上那个点,因为&运算符没有短路。 - Captain Man

4

了解它的一种方法是测试它!怎么测试呢?好的,制作一个打印输出内容的方法:

public static boolean test(int i)
{
    System.out.println(i);
    return false;
}

...

if (test(1) && test(2) && test(3))
{
    // not reached
}

这将打印出:
1

所以,对于你的问题,答案是“不”。

2

最好的方法是尝试一下,特别是对于一个单行问题。这样做会更快。

答案是Java不会执行“if”的主体。


真的,但“通过实验证明”的方法并不总是最好的选择。例如,在单核机器上测试并发相关的东西是很有意义的。了解底层机制而不是希望你的测试包括黑盒子的所有边缘情况总是很好的选择... - Andrzej Doyle
1
记住,我们在谈论一行代码。 "边缘情况"?在这种情况下不需要。 - duffymo

2
这段代码不会抛出任何NullPointerException异常。条件从左到右依次进行评估,一旦发现第一个false表达式,剩余的表达式将不再被评估。

2

1

Java有短路求值,所以这没问题。

代码看起来没问题,但你真的需要检查object.field != null吗?我认为可以省略该测试,因为你从未使用该变量,只是设置它。

顺便说一下,大多数程序员不会直接访问字段(object.field),而是通过getter/setter(object.setField(x);)进行访问。没有更多上下文可供参考,我无法确定在你的情况下是否适用。


1

&& 和 || 条件会在它们能够确定条件是真/假的时候停止,对于你的情况,条件将在 object != null 后立即停止,我认为你的代码在这种情况下很好。


0

虽然短路计算在这里可以工作,但并不能保证(就像我经常做的那样)在编写另一个语句时不会出现顺序错误。更好的做法是嵌套这些if语句并定义您希望布尔检查中断的顺序:

if(object != null) 
{
    if(object.field != null)
    {
        object.field = "foo";
    }
}

这段代码的作用与你所说的完全相同,如果第一个布尔检查失败,则不执行第二个;同时它也是空指针安全的,因为只有在对象不为空时才会检查 object.field。

在布尔值上使用短路运算符后期可能会变得很麻烦,因为当你有多个布尔 if 语句时,要有效地调试哪一部分被短路了就变得更加棘手。


0
如果您想评估所有布尔表达式而不考虑每个表达式的真值,则可以使用 & 和 | 而不是 && 和 ||。但请确保仅在布尔表达式上使用它们。与 && 和 || 不同,& 和 | 对于数字类型也有一种完全不同于布尔类型的含义。 http://ibiblio.org/java/course/week2/46.html

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接