【问题标题】:Null check in an enhanced for loop增强的 for 循环中的空值检查
【发布时间】: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(...):stackoverflow.com/a/34913556/5637185

标签: java syntax loops for-loop


【解决方案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 documentationsource

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,则抛出异常。

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-04-28
              • 2014-02-23
              • 1970-01-01
              • 2011-01-20
              • 1970-01-01
              • 2012-08-22
              • 1970-01-01
              相关资源
              最近更新 更多