Val
Val

Reputation: 11107

(Linked)BlockingQueue.put(null) throws NullPointerException

I have checked the implementation, it does so intentionally

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

This surprise is not convenient for user (who wants to signal end of stream this way, for instance) and breaks the general contract with collections, which easily accept the null elements. What is the point of BlockingQueue to discriminate null elements? If nulls are so bad, might be we should refrain using them at all and enforce this low in JLS?

Upvotes: 14

Views: 6191

Answers (1)

Louis Wasserman
Louis Wasserman

Reputation: 198093

Accepting nulls is not part of the Collection contract. Indeed, the Collection Javadoc specifically states:

Some collection implementations have restrictions on the elements that they may contain. For example, some implementations prohibit null elements, and some have restrictions on the types of their elements. Attempting to add an ineligible element throws an unchecked exception, typically NullPointerException or ClassCastException.

In many cases, adding null to a collection means there's a bug in your program somewhere, not that you put it in deliberately. For example, the Guava library (which I contribute to) makes the explicit decision to reject nulls from many of their collection implementations, specifically the immutable ones:

We did an exhaustive study on Google's internal code base that indicated that null elements were allowed in collections about 5% of the time, and the other 95% of cases were best served by failing fast on nulls.

There are generally workarounds that do accept nulls, but many collection implementations make the decision to reject nulls (which most users find helpful, as it helps them find bugs) and offer workarounds for the rare case where explicit nulls are appropriate.

In all honesty, I think the reason that LinkedBlockingQueue is in this category is that all this hadn't been figured out when the original collections framework was developed, but it was pretty clear by the time that the concurrent collections were being added. Doug Lea, who did much of the work on util.concurrent, has been quoted as saying,

Null sucks.

In the worst case, object wrappers or "poison objects" are always valid workarounds; Guava provides an Optional class which can serve that role in many cases, which is discussed extensively here on StackOverflow.

Upvotes: 14

Related Questions