空检查在增强的for循环中


171

在Java中的for循环中防止空值的最佳方法是什么?

这看起来很丑:

if (someList != null) {
    for (Object object : someList) {
        // do whatever
    }
}

要么

if (someList == null) {
    return; // Or throw ex
}
for (Object object : someList) {
    // do whatever
}

可能没有其他办法。他们是否应该将其放入for构造本身中,如果为null,则不要运行循环?


2
您最好扔一个NPE。null与空集合不同。
Tom Hawtin-大头钉

6
@GregMattes 2月的问题与10月的问题如何重复?
2013年

1
只需使用Collections.nonNullElementsIn(...):stackoverflow.com/a/34913556/5637185
Jeffrey Dilley 2016年

Answers:


226

您最好验证从哪里获得该列表。

空列表就是您所需要的,因为空列表不会失败。

如果您从其他地方获得此列表,并且不知道是否可以,则可以创建一个实用程序方法并像这样使用它:

for( Object o : safe( list ) ) {
   // do whatever 
 }

当然safe是:

public static List safe( List other ) {
    return other == null ? Collections.EMPTY_LIST : other;
}

57
请注意,Collections.emptyList()将避免分配额外的对象(IIRC)。
乔恩·斯基特

7
@Jon:我一直问自己,那emptyList java.sun.com/j2se/1.5.0/docs/api/java/util/的用途是 什么?IIRC是什么?
OscarRyz

11
IIRC =“如果我没记错的话”。是的,对于所有对Collections.emptyList()的调用都会返回一个单例实例。
ColinD

这实际上并不能回答问题。为什么会接受答案?
Christopher Wirt

1
@ChristopherWirt,因为它确实回答了问题:D
Tarik

100

如果传入null,则可能编写一个助手方法,该方法将返回空序列:

public static <T> Iterable<T> emptyIfNull(Iterable<T> iterable) {
    return iterable == null ? Collections.<T>emptyList() : iterable;
}

然后使用:

for (Object object : emptyIfNull(someList)) {
}

我认为我实际上不会这样做-我通常会使用您的第二种形式。特别是,“或throw ex”很重要-如果它确实不应该为null,则应该抛出异常。你知道的东西出了问题,但你不知道损害的程度。提前中止。


3
我会将Iterable <T>列表参数更改为Iterable <T> iterable,因为并非每个iterable都是一个列表。
龙目

使用此方法时要小心:由于使用了Collections类,因此此方法的使用涉及到您的列表是不可变的
Tanorix

@tanorix:用什么方式?
乔恩·斯基特

@JonSkeet,您可以看到Collections类的emptyList()返回一个不可变列表:docs.oracle.com/javase/8/docs/api/java/util/…因此,如果用户不想让他的列表不可变,则可以有问题
Tanorix

@tanorix:但是这个问题的重点是关于返回值的迭代。那不会修改它。这就是为什么返回类型emptyIfNullIterable<T>-上有一个不幸的remove方法Iterator<T>,但这是它唯一可变的方面(如果您有一个空集合,为什么要尝试从中删除任何内容?)目前尚不清楚反对这里。
乔恩·斯凯特

29

已经是2017年了,现在您可以使用Apache Commons Collections4

用法:

for(Object obj : ListUtils.emptyIfNull(list1)){
    // Do your stuff
}

您可以使用来对其他Collection类执行相同的null安全检查CollectionUtils.emptyIfNull


2
尽管可以创建不必要的列表对象,但仍可以使用。CollectionUtils.ifNotEmpty可能更冗长,但效率更高,更快。并不是那么重要...
劳伦斯

2
在2017年,我期望List.emptyIfNull(list1)
Dima

3
@Lawrence,该方法不会创建新的列表对象,而是Collections.emptyList()在内部使用,这反过来总是返回相同的预分配的空不可修改列表。
Yoory N.

如果调用myobject.getCompanies()。getAddresses()并且都返回一个List且都可以为null怎么办?
粉366

9

使用Java 8 Optional

for (Object object : Optional.ofNullable(someList).orElse(Collections.emptyList())) {
    // do whatever
}

1
它比简单的三元运算符更冗长,someList != null ? someList : Collections.emptyList()并且还会创建并立即丢弃Optional对象的实例。
Yoory N.

2
与简单的if(someList == null)语句相比,这些怪异的行如何优雅?让我们在一行中编写一个银行应用程序...
Andreas Panagiotidis,

7

如果List要从实现的方法调用中获得该结果,则不返回null,返回一个empty List

如果您无法更改实现,那么您将无法进行null检查。如果不应该null,则抛出异常。

我不会选择返回一个空列表的helper方法,因为它有时可能有用,但是随后您将习惯于在每次可能隐藏一些bug的循环中调用它。


7

使用ArrayUtils.nullToEmpty来自commons-lang于阵列库

for( Object o : ArrayUtils.nullToEmpty(list) ) {
   // do whatever 
}

该功能存在于commons-lang大多数Java项目中都包含的库中。

// ArrayUtils.nullToEmpty source code 
public static Object[] nullToEmpty(final Object[] array) {
    if (isEmpty(array)) {
        return EMPTY_OBJECT_ARRAY;
    }
    return array;
}

// ArrayUtils.isEmpty source code
public static boolean isEmpty(final Object[] array) {
    return array == null || array.length == 0;
}

这与@OscarRyz给出的答案相同,但是出于DRY的口头禅,我相信这是值得注意的。请参阅commons-lang项目页面。这是nullToEmptyAPI 文档

commons-lang如果尚未将Maven条目包括在您的项目中。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>

不幸的是,commons-lang没有为List类型提供此功能。在这种情况下,您将必须使用如前所述的辅助方法。

public static <E> List<E> nullToEmpty(List<E> list)
{
    if(list == null || list.isEmpty())
    {
        return Collections.emptyList();
    }
    return list;
}

4

我已经修改了上面的答案,所以您不需要从Object进行投射

public static <T> List<T> safeClient( List<T> other ) {
            return other == null ? Collections.EMPTY_LIST : other;
}

然后只需调用列表

for (MyOwnObject ownObject : safeClient(someList)) {
    // do whatever
}

说明:MyOwnObject:如果List<Integer>是这种情况,则MyOwnObject将为Integer。


1

一种有效防止for循环中为null的方法是用Google Guava包装您的集合,Optional<T>因为希望这样可以清除有效空集合的可能性,因为希望客户检查该集合是否存在Optional.isPresent()



0

使用CollectionUtils.isEmpty(Collection coll)Null安全检查方法,检查指定的集合是否为空。

为此import org.apache.commons.collections.CollectionUtils

Maven依赖

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.0</version>
</dependency>

-4
for (Object object : someList) {

   // do whatever
}  throws the null pointer exception.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.