Java 是不是会检查“&&”(和)运算符中的所有参数,即使其中一个参数为假?

Posted

技术标签:

【中文标题】Java 是不是会检查“&&”(和)运算符中的所有参数,即使其中一个参数为假?【英文标题】:Does Java check all arguments in "&&" (and) operator even if one of them is false?Java 是否会检查“&&”(和)运算符中的所有参数,即使其中一个参数为假? 【发布时间】:2011-05-09 00:04:52 【问题描述】:

我有这样的代码:

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

假设对象为空。

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

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

【问题讨论】:

玩转:ideone.com/KRMwj 另一种情况:ideone.com/NAP0Q 【参考方案1】:

&& 会短路,而& 不会。

但是对于这样简单的问题,最好只是尝试一下(当您无法使用机器时,ideone 可以提供帮助)。

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

最后确定检查的地方是JLS §15.23。不是最容易阅读的东西,相关部分指出: && 运算符类似于 & (§15.22.2),但仅当其左侧操作数的值为真时才计算其右侧操作数。

【讨论】:

【参考方案2】:

Java 确实有短路评估,即您的代码应该没问题

【讨论】:

Java 确实存在短路,但它仅在本示例中使用,因为使用了 && 而不是 && 将导致 NullPointerException "&& 而不是 &"?您在问题的什么地方看到了这一点? 无处,我只是添加了这一点,因为& 运算符确实没有有短路。【参考方案3】:

找出答案的最佳方法是尝试一下,尤其是对于单行问题。也会更快。

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

【讨论】:

没错,但“实验证明”并不总是最好的方法。例如,考虑在单核机器上测试与并发相关的东西。询问和理解底层机制总是好的,而不是希望你的测试包括黑盒的所有边缘情况...... 请记住,我们在这里讨论的是一行代码。 “边缘案例”?在这种情况下不是。【参考方案4】:

这不会抛出任何 NullPointerException 。条件将从左到右进行计算,并且在找到第一个 false 表达式的那一刻,它不会计算剩余的表达式。

【讨论】:

【参考方案5】:

一种了解它的方法!测试它!如何?好吧,制作一个打印出一些东西的方法:

public static boolean test(int i)

    System.out.println(i);
    return false;


...

if (test(1) && test(2) && test(3))

    // not reached

这打印:

1

所以你的问题的答案是“否”。

【讨论】:

【参考方案6】:

也许这个其他问题可以帮助你:

Differences in boolean operators: & vs && and | vs ||

【讨论】:

【参考方案7】:

Java 有短路评估,所以没问题。

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

附带说明,大多数程序员不会直接访问字段 (object.field),而是通过 getter/setter (object.setField(x);)。没有更多的上下文,我不能说这是否适合你的情况。

【讨论】:

【参考方案8】:

&& 和 ||条件在他们可以决定条件是真/假的点停止,在您的情况下,条件将在object != null 之后立即停止,我认为您的代码对于这种情况来说很好

【讨论】:

【参考方案9】:

如果您希望计算所有布尔表达式而不考虑每个表达式的真值,那么您可以使用 & 和 |而不是 && 和 ||。但是请确保仅在布尔表达式上使用这些。与 && 和 || 不同,& 和 |数字类型的含义也与布尔值的含义完全不同。 http://ibiblio.org/java/course/week2/46.html

【讨论】:

【参考方案10】:

虽然短路可以在这里工作,但它不能保证(就像我多次做过的那样)你在编写另一个时会弄错顺序,最好嵌套这些 if 语句并定义你想要的顺序要打破的布尔检查:

if(object != null) 

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

这与您本质上所说的完全相同,如果第一个布尔检查失败,则不要执行第二个;它也是 nullPointerException 安全的,因为除非 object 不为 null,否则不会检查 object.field

在布尔值上使用短路可能会在以后变得烦人,因为当您有多个 bool if 语句时,有效地调试哪个部分短路变得更加棘手。

【讨论】:

以上是关于Java 是不是会检查“&&”(和)运算符中的所有参数,即使其中一个参数为假?的主要内容,如果未能解决你的问题,请参考以下文章

检查数字是不是为 Kaprekar

检查三个布尔值中的两个是不是为真?

如何检查游戏对象是不是处于活动状态

检查列是不是包含有效值

检查变量是不是在临时值列表中

if可以检查多少个条件