增强的 for 循环中的空值检查

Posted

技术标签:

【中文标题】增强的 for 循环中的空值检查【英文标题】:Null check in an enhanced for loop 【发布时间】:2011-01-16 00:59:26 【问题描述】:

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

这看起来很丑:

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

或者

if (someList == null) 
    return; // Or throw ex

for (Object object : someList) 
    // do whatever

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

【问题讨论】:

你最好还是扔一个 NPE。 null 与空集合不同。 @GregMattes 2 月的问题与 10 月的问题是如何重复的? 只需要使用Collections.nonNullElementsIn(...):***.com/a/34913556/5637185 【参考方案1】:

使用 commons-lang 库中的 ArrayUtils.nullToEmpty 用于数组

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 项目页面。这是nullToEmpty API documentation 和 source

Maven 条目以将 commons-lang 包含在您的项目中(如果还没有的话)。

<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;

【讨论】:

【参考方案2】:

使用 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>

【讨论】:

【参考方案3】:

使用 Java 8 Optional

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

【讨论】:

它比简单的三元运算符如someList != null ? someList : Collections.emptyList() 更冗长,并且还创建并立即丢弃Optional 对象的实例。 这些怪物行如何比简单的 if(someList==null) 语句更优雅。让我们用一行写一个银行应用程序......【参考方案4】:

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

用法:

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

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

【讨论】:

虽然会创建不必要的列表对象,但会起作用。 CollectionUtils.ifNotEmpty 可能更冗长但更有效和更快。没关系…… 2017 年我希望 List.emptyIfNull(list1) @Lawrence,该方法不创建新的列表对象,它在内部使用Collections.emptyList(),而它又总是返回相同的预分配空的不可修改的列表。 如果你调用 myobject.getCompanies().getAddresses() 并且都返回一个 List 并且两者都可以为 null 怎么办?【参考方案5】:

对于任何对编写自己的静态空安全方法不感兴趣的人,您可以使用:commons-lang 的org.apache.commons.lang.ObjectUtils.defaultIfNull(Object, Object)。例如:

    for (final String item : 
    (List<String>)ObjectUtils.defaultIfNull(items, Collections.emptyList()))  ... 

ObjectUtils.defaultIfNull JavaDoc

【讨论】:

对我来说,这个答案是最优雅的 另一种使用Java原生Objects类的类似方法是Objects.requireNonNullElse(itemsList, new ArrayList&lt;String&gt;())【参考方案6】:
for (Object object : someList) 

   // do whatever
  throws the null pointer exception.

【讨论】:

【参考方案7】:

我已经修改了上面的答案,所以你不需要从 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&lt;Integer&gt;,那么在这种情况下,MyOwnObject 将是 Integer。

【讨论】:

【参考方案8】:

在 for 循环中有效防止 null 的另一种方法是使用 Google Guava 的 Optional&lt;T&gt; 包装您的集合,因为人们希望这样可以明确有效地为空集合的可能性,因为客户需要检查是否该集合与Optional.isPresent() 一起出现。

【讨论】:

【参考方案9】:

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

你只需要一个空列表,因为一个空列表不会失败。

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

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

当然safe 是:

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

【讨论】:

请注意,Collections.emptyList() 将避免分配额外的对象 (IIRC)。 @Jon:我一直在问自己,emptyListjava.sun.com/j2se/1.5.0/docs/api/java/util/…IIRC 有什么用? IIRC = "如果我没记错的话"。是的,所有对 Collections.emptyList() 的调用都会返回一个单例实例。 这...实际上并没有回答这个问题。为什么它被接受? @ChristopherWirt 因为它确实回答了这个问题:D【参考方案10】:

如果你传入 null,你可能会编写一个返回空序列的辅助方法:

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

然后使用:

for (Object object : emptyIfNull(someList)) 

我不认为我真的会这样做 - 我通常会使用你的第二种形式。特别是,“or throw ex”很重要——如果它真的不应该为空,你肯定应该抛出一个异常。您知道某事出了问题,但您不知道损坏的程度。提前中止。

【讨论】:

我会将 Iterable 列表参数更改为 Iterable 可迭代,因为并非每个可迭代都是列表。 谨慎使用此方法:由于使用了 Collections 类,使用此方法涉及到您的列表是不可变的 @tanorix:以什么方式? @JonSkeet 你可以看到 Collections 类的 emptyList() 返回一个不可变的列表:docs.oracle.com/javase/8/docs/api/java/util/… 所以如果用户不想让他的列表不可变,这可能会有问题 @tanorix:但这个问题的重点是对返回值进行迭代。那不会修改它。这就是为什么emptyIfNull 的返回类型是Iterable&lt;T&gt; - 在Iterator&lt;T&gt; 上有不幸的remove 方法,但这是它唯一可变的方面(如果你有一个空集合,你为什么要尝试从中删除任何内容?)不清楚您在这里反对什么。【参考方案11】:

如果您从您实现的方法调用中获得 List,则不要返回 null,而是返回一个空的 List

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

我不会使用返回空列表的辅助方法,因为它有时可能很有用,但你会习惯在每个循环中调用它,可能会隐藏一些错误。

【讨论】:

以上是关于增强的 for 循环中的空值检查的主要内容,如果未能解决你的问题,请参考以下文章

Java中的增强for循环怎么用?for()中的参数是啥意思

Java 中的foreach(增强for循环)

php怎么去除数组中的空值

在java中,新循环,也就是增强for循环怎么用?是啥格式?

如何正确遍历删除List中的元素(普通for循环增强for循环迭代器iteratorremoveIf+方法引用)

增强for循环