这个 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。