12

我已经检查了实现,它是故意这样做的

 public void put(E e) throws InterruptedException {
     if (e == null) throw new NullPointerException();

这个惊喜对于用户(例如,想要以这种方式发出流结束信号)来说并不方便,并且打破了与集合的一般合同,这些集合很容易接受空元素。BlockingQueue 区分空元素的意义何在?如果空值如此糟糕,我们是否应该完全避免使用它们并在 JLS 中强制执行这个低值?

4

1 回答 1

14

接受空值不是Collection合同的一部分。事实上,Collection Javadoc明确指出:

一些集合实现对它们可能包含的元素有限制。例如,一些实现禁止空元素,而一些实现对其元素的类型有限制。尝试添加不合格的元素会引发未经检查的异常,通常是 NullPointerException 或 ClassCastException。

在许多情况下,添加null到集合中意味着您的程序中某处存在错误,而不是您故意将其放入。例如,Guava 库(我参与其中)做出了明确的决定,拒绝来自其许多集合实现的空值,特别是不可变的:

我们对 Google 的内部代码库进行了详尽的研究,结果表明大约 5% 的时间集合中允许空元素,而其他 95% 的情况最好通过在空值上快速失败来解决。

通常有一些解决方法确实接受空值,但许多集合实现决定拒绝空值(大多数用户认为这很有帮助,因为它可以帮助他们发现错误)并为显式空值合适的罕见情况提供解决方法。

老实说,我认为属于LinkedBlockingQueue这一类的原因是在开发原始集合框架时所有这些都没有被弄清楚,但是在添加并发集合时已经很清楚了。Doug Lea 在 上做了很多工作util.concurrent,他被引述说,

空很烂。

在最坏的情况下,对象包装器或“毒对象”始终是有效的解决方法;Guava 提供了一个Optional可以在许多情况下充当该角色的类,这在 StackOverflow 上进行了广泛讨论

于 2012-05-31T09:15:54.980 回答