在我的代码中,当NullPointerException
为null时,我通常使用这种方法来避免List
in语句:
if (myList != null && myList.size() > 0) {
for ( MyObj obj : myList ) {
System.out.println("MyObjStr: "+obj);
}
}
是否有其他方法可以在不写“if”语句的情况下执行相同操作,但使用相同的“for”语句?
答案 0 :(得分:11)
不需要检查尺寸。如果列表中没有对象,则不会执行for循环。
只有在您不确定对象的状态时,才需要检查null
。但是当使用你自己的对象时(例如,没有通过争论从外部给出),那么就不需要进行空检查。
请参阅Avoiding “!= null” statements in Java?,了解为什么没有经验的开发人员通常会使用空检查进行分解。
答案 1 :(得分:4)
你不想只是"避免NPE"。 NPE是一种注意编程错误的好方法,因此您必须小心需要进行空检查的内容。许多程序员在防御性的地方进行无效检查,因为他们不再信任API合同。
如果您的NPE中包含无理由为的内容,那么您之前就做错了(这是因为您的集合未初始化)。你不想隐藏它,你希望它在你脸上爆炸,所以你可以立即修复它(快速原则)。
如果 null
是变量的可能(且有意义的)值(或者如果值来自外部源),则需要对其进行空值检查。但是,您必须处理此案例,不要只是跳过生成NPE的代码。如果你只是跳过它,那么后来的代码就不比当前的代码更安全,并且对于同一个变量将再次需要进行空检查。
@ifLoop提供了一个关于这个主题的另一篇文章的非常好的链接,所以我在这里复制它,因为我的答案被接受了: Avoiding “!= null” statements in Java?
附注:循环不需要进行尺寸检查。如果集合为空,则只会跳过循环。
答案 2 :(得分:2)
这是一种优雅的方式,可以在similar post中找到。使用
for( Object o : safe( list ) ) {
// do whatever
}
public static List safe( List other ) {
return other == null ? Collections.EMPTY_LIST : other;
}
有人说,让你的方法返回空数组而不是null是一个好习惯。例如,您可以返回
return Collections.EMPTY_LIST;
在每个catch
块中。
通过这种方式,您可以安全地循环使用它们,当您获得NPE时,您就会知道代码而不是数据有问题。在这方面,正如@Joffrey所说,NPE将非常受欢迎
答案 3 :(得分:1)
嗯,你可以做到一行,但有可读性损失:
for ( MyObj obj : (myList == null ? new ArrayList<MyObj>() : myList) ) {
System.out.println("MyObjStr: "+obj);
}
答案 4 :(得分:0)
还有另一种避免将NULL传递到for(forEach)循环的可能性-我们之前可以使用 CollectionUtils 库中的 isNotEmpty(Collection coll)方法。
示例:
if (CollectionUtils.isNotEmpty(someCollection)) {
for (Item item: someCollection) {
...
}
}
或:
if (CollectionUtils.isNotEmpty(someCollection)) {
someCollection.forEach(...);
}
答案 5 :(得分:0)
在很多情况下,您应该进行将DTO传入另一个对象的映射练习。发送空集合而不是null可能会浪费流量,甚至通过使用排除null
mapper.setSerializationInclusion(Include.NON_NULL);
甚至mapper.setSerializationInclusion(Include.NON_EMPTY);
也就是说,如果您需要执行以下操作:
Collection<Dto> dtos = null;
for(Dto dto: dtos) {
//doSomething
}
您必须使用if
保护(好的,但是我更喜欢另一种方式),或者坚持使用NullObject习惯用法(好):
Collection<Dto> safeDtos = Optional.ofNullable(dtos).orElse(Collections.emptyList());
for(Dto dto: safeDtos) {
//doSomething
}
相同,但对于流:
Optional.ofNullable(dtos).orElse(Collections.emptyList()).stream()
.map(this::doSomething)
.collect(Collectors.toList());
此外,除了进行映射操作外,请不要泄漏任何下游代码中的DTO。在DTO和其余代码之间,应该有一个保护边界。
DTO->映射->域对象(或另一个保存NPE的中间对象,也许有枚举而不是字符串等)->代码的其余部分。