空指针异常,具体取决于 OR 语句的顺序



这个 for 循环应该通过一个字符串数组,如果数组包含空值或空字符串,则值 hasEmpty true。下面的代码给了我一个NullPointerException。

String[] names = {null, "B", "C"};
    boolean hasEmpty = false;
    for(int i = 0; i<names.length; i++){
        if ((names[i].equals("")) || (names[i] == null))
            hasEmpty = true;
    }

但是,如果我更改 if 子句中 OR 语句的顺序,以下代码似乎有效。有人可以告诉我为什么会这样吗?

String[] names = {null, "B", "C"};
    boolean hasEmpty = false;
    for(int i = 0; i<names.length; i++){
        if ((names[i] == null) || (names[i].equals("")))
            hasEmpty = true;
    }

因为||是短路算子。一旦它找到一个从左到右的操作数为真,它甚至不会计算其他操作数(因为true or anything总是为真)。

&

& 也是如此:如果第一个操作数为 false,它确实会评估其他操作数,因为false && anything总是 false。

性能取决于您有多少空值和空字符串。也许这就是您首先选择检查空字符串的原因,因为它发生得更频繁。您也可以这样做,但也应避免空指针异常。有一个简单的技巧可以做到这一点 - 依靠你的代码,而不是数据。如果您简单地更改与内容进行比较的内容并使用您的常量,那么它将正常工作。常量不为空,因为它们确实存在。

if (("".equals(names[i])) || (names[i] == null)){/* Handling empty or null strings */}

看到区别了吗?

||首先检查第一个条件,它面临null...在null上调用equals会抛出NullPointerException

当您首先检查null时,第一个条件的计算结果将为true因此它将跳过检查第二个条件

检查这一点以了解 java 中单运算符和双运算符或/和逻辑运算符之间的区别

正如预期的那样。

如果 OR 语句的第一个参数为真,则不需要计算另一个参数。

对于 AND 语句和假值也是如此。如果第一个是假的,则无需评估第二个。

if语句中的代码是延迟计算的,这意味着如果它们知道自己会失败,它们可以退出。第一个失败,因为您正在调用null.equals("")这将引发错误。第二个成功是因为您正在检查names[i]是否null,如果是,循环退出。

if ((names[i] == null ) ||
    (names[i].equals(""))) // Don't bother checking if names[i] is null

if ((names[i].equals("")) ||
    (names[i] == null)) // Check null only if names[i].equals("") is false

||反转为&&可能更有意义:

if (names[i] != null && !names.equals(""))

equals()方法需要字符串不null,如果值为 null,则它不再是对象,您实际上调用 null.equals。someOtherObject),然后它会按预期抛出NullPointerException

String[] names = {null, "B", "C"};
boolean hasEmpty = false;
for(int i = 0; i<names.length; i++){
       /* change here */
        if (("".equals(names[i])) || (names[i] == null))
            hasEmpty = true;
    }

原因:您正在尝试将空值与字符串进行比较,因此在第一个代码片段中,您得到了 NullPointerException。但是在第二个代码中,您更改了这两个条件的位置。OR条件的评估如下:


如果满足第一个条件,则仅检查下一部分。

表示如果 (a || b)

如果 A 为真,则不会评估 B。但如果 A 为假,则将评估 B。

最新更新