【问题标题】:(Linked)BlockingQueue.put(null) throws NullPointerException(Linked)BlockingQueue.put(null) 抛出 NullPointerException
【发布时间】:2012-06-05 12:48:34
【问题描述】:

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

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

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

【问题讨论】:

    标签: java collections null nullpointerexception


    【解决方案1】:

    接受空值不是Collection 合约的一部分。确实,CollectionJavadoc 明确指出:

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

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

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

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

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

    Null 很糟糕。

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

    【讨论】:

    • 好的,BlockingQueue 有什么特别之处需要它来阻止空值?如果没有,那为什么其他收藏不这样做呢?
    • 问题是不能完全禁止空值。除了完全破坏向后兼容性(Sun 和 Oracle 一直非常小心地不这样做,即使这意味着在 Java 中保留明显的错误和坏库),你不能避免它,例如在对象数组上:当你说new String[5] 时,如果不是null,数组还会填充什么?这很不愉快,但即使我们想摆脱它也不清楚。
    • 当然不在集合中,但我们不能从 Java 语言中完全删除 arrays。此外,许多集合实现在内部使用数组。综上所述,在 JVM 上运行的 languages 确实禁止 null。即使我们不能在 Java 中更改它,其他语言也可以并且确实禁止 null。
    • 没有人禁止任何事情。库开发人员只是让它稍微困难,例如使用空值,这样您就不会毫无意义地朝自己的脚开枪,但是仍然有解决方法。 (我不了解你,但我很高兴我正在使用一种难以或不可能出现段错误的语言,即使 C 或 C++ 专家可以编写通常不会出现段错误的程序;它更多或不一样的原理。)
    • @Val FWIW 四年后 - “BlockingQueue 有什么特别之处需要它来阻止空值?”。好吧,一方面poll(long timeout, TimeUnit unit) 使用null 表示发生了超时。如果该类使用 TimeoutException 来代替此目的,则允许 null 值可能会很好,但事实并非如此。
    猜你喜欢
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 2014-09-15
    • 2018-11-15
    • 2017-08-11
    • 2013-09-07
    • 2013-06-18
    相关资源
    最近更新 更多