【问题标题】:Iterator null collection迭代器空集合
【发布时间】:2012-07-07 13:57:27
【问题描述】:

当不确定集合引用是否为 null 时,我必须在迭代之前检查 null 是很常见的。 示例:

Collection<Object> collection = ...
...
if(collection != null)//troublesome
    for(Object o : collection)

当然,我知道空集合比 null 好得多,但在某些情况下,客户端代码无法控制来自其他模块的可为空集合(例如,来自 3rd 方代码的返回值)。 于是我写了一个实用方法:

public static <T> Iterable<T> nullableIterable(Iterable<T> it){
    return it != null ? it : Collections.<T>emptySet();
}

在客户端代码中,不再需要检查null:

for(Object o : nullableIterable(collection))
...

你觉得nullableIterable()合理吗?有什么建议吗?有什么顾虑吗?谢谢!

【问题讨论】:

  • 是的,我也这样做。我的方法叫nullSafe()...
  • @LukasEder nullSafe() 返回什么默认 Iterable 实例?
  • 我在实用程序类中重载了nullSafe(List)nullSafe(Set) 等...但是您的想法也很有效,因为您只公开了Iterable 类型。具体的Iterable 实现与调用站点无关
  • 如果有人选择通过忽略空值来进行代码防御,这是很好的方法stackoverflow.com/a/2250056/1506477

标签: java collections iterator


【解决方案1】:

看起来不错。我个人也是这样做的。您总会遇到不同意这一点的开发人员,因为它是一种防御性编程。假设您有一个不应该返回null 的工作流或类。这意味着从中获取null 是一个错误,您的代码将隐藏它,因为它会将null 变成一个空集合,并且该错误永远不会出现。

例如,如果您正在编写不支持 null 集合的 API,那么您应该避免这种情况。如果客户端代码为您提供了一个您不支持的 null 集合,您应该抛出一个 IllegalArgumentException 以让客户端代码知道所提供的集合有问题。比如:

public void myApiNoSupportForNull(Collection<Object> collection){
   // Pre condition
   if(collection == null) 
     throw new IllegalArgumentException("This API does not support null collections!");
   //...
}

【讨论】:

  • 同意。所以我应该告诉客户端代码如何使用该方法并注意陷阱。我可能会为该方法编写一些 Javadoc。
  • 或者抛出 IllegalArgumentException 并返回,以便客户端代码知道您不支持 null 集合
  • some 可能会这样争论,是的。但是一些 API 被设计为“支持”null 和空列表。以File.list() 为例。它可以在某些情况下返回null,这不一定是错误。注意:同样对于 一些 API,如果语义相同,接受 null 代替空集合可能会很方便
  • @LukasEder 我完全同意你的看法。这一切都取决于您公开的 API。
  • 你为什么声称这是一个错误?我有这样的设计,我认为集合不是为了性能而初始化的。为什么它是一个错误?
【解决方案2】:

如果您将此功能的使用限制在与“外部”代码交互的层,并确保您永远不会开始使用它来防御自己或同事,这对我来说看起来不错。 考虑使用 @Nullable 注释对代码中的参数和字段进行注释 - 假设未注释的内容不能为空,这非常有用,尤其是考虑到 IDE 和静态分析工具都知道此注释。

【讨论】:

    【解决方案3】:

    在大多数情况下,这是可以的。
    请记住,您可能会遇到第三方在 error 的情况下返回 null ,并且空列表是有效的结果。
    因此,我会考虑更改您的代码并执行以下操作:

    public static <T> Iterable<T> nullableIterable(Iterable<T> it, boolean exceptionIfNull){
        if (exceptionIfNull && it == null) {
            throw new NUllPointerException("Iterable is null");
        } else
        return it != null ? it : Collections.<T>emptySet();
    }
    
    public static <T> Iterable<T> nullableIterable(Iterable<T> it){
        return nul,lableIterable(it,false); //Default behavior for most cases
    }
    

    【讨论】:

      猜你喜欢
      • 2014-05-17
      • 2012-12-29
      • 2020-08-09
      • 2012-04-19
      • 2010-09-16
      • 1970-01-01
      • 1970-01-01
      • 2014-12-27
      • 2011-04-25
      相关资源
      最近更新 更多