Java 7 更改了 Collections.checkedCollection 的行为以允许 null。 API 在混合环境中使用它是否仍然值得?

标签 java compatibility java-7

首先,这是 Java 7's Collections.checked* 添加的行为:

Since null is considered to be a value of any reference type, the returned collection permits insertion of null elements whenever the backing collection does.

这似乎没有列在 compatibility documentation 中, 尽管。演示:

public class MyAPI {
    private Set<Polygon> polygons = new Collections.checkedSet(new HashSet<Polygon>(), Polygon.class);
    public Set<Polygon> getPolygons() {
        return polygons;
    }
}
public class MyAPITest {
    // This JUnit test passes when using Java 6 or earlier, but fails for Java 7.
    @Test(expected=NullPointerException.class)
    public void testAddNullPolygon() {
        new MyAPI().getPolygons().add(null);
    }
}

正如您所看到的,我正在编写一个 API,它公开一个 Set 供客户端代码填充。据我所知,这是 Collections.checkedCollection 等的用例之一:添加的运行时检查有助于防止插入奇怪的东西。

无论如何,我已经更改了 API 来处理 null,但我担心客户端代码有时会抛出 NPE,有时不会,具体取决于最终用户运行的 Java 版本。就是感觉很 splinter 。理想情况下,我想保留旧的行为,防止插入时出现空值。

我想我的选择是:

  1. 完全放弃运行时检查。

  2. 不用担心,并相信客户端代码永远不会插入空值。

  3. 声明我的 API 仅支持 JRE 7。

  4. 使用 Guava,它看起来很棒,但它是我的 API 需要承担的额外依赖项。

  5. 推出我自己的 Set 包装器,强制执行 null 和类型检查。

  6. 我缺少的一些其他更优雅的解决方案。

任何指导将不胜感激!

最佳答案

我最终选择的选项是删除checkedCollection,使公开的集合不可修改。 API 的用户需要调用额外的添加/删除/清除方法之一来修改集合。

这在一定程度上限制了 API 用户:例如,他们无法在单个方法调用中使用 addAll 复制另一个集合的所有元素。但这是简单性和类型安全性之间的公平权衡。

public class MyAPI {
    private Set<Polygon> polygons = new HashSet<Polygon>();
    private Set<Polygon> polygonsReadonlyView = Collections.unmodifiableSet(polygons);
    public Set<Polygon> getPolygons() {
        return polygonsReadonlyView;
    }
    public boolean addPolygon(Polygon p) {
        if (p == null) {
            throw new IllegalArgumentException("polygon cannot be null");
        }
        return polygons.add(p);
    }
    public boolean removePolygon(Polygon p) {
        return polygons.remove(p);
    }
    public void clearPolygons() {
        polygons.clear();
    }
}

所有这一切的一个要点是永远不要依赖checkedCollection来防止插入空值。

Google 搜索可能会建议这样做...但不要这样做!空检查不是checkedCollection 的用例之一。

关于Java 7 更改了 Collections.checkedCollection 的行为以允许 null。 API 在混合环境中使用它是否仍然值得?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12147898/

相关文章:

java - 如何将数组的值添加到一个矩阵的列?

Java 使用 XPath 解析 iTunes XML 库

java - 编译隔离的java文件

java - 比较方法违反了它的一般契约!静态分析可以吗?

java - 如何在android后台服务中监听蓝牙套接字?

Java抽象类实现接口(interface)

scala - 是否计划在 Scala 的 future 版本中进行任何语言或规范更改?

android - Android API <11 上的 AsyncTask Thread_Pool_Executor

java - Java 7 中的闭包

java - x in y 定义在一个不可访问的类或接口(interface)中,ID in structure