Why does java.util.ArrayList allow to add null?

  • I wonder why java.util.ArrayList allows to add null. Is there any case where I would want to add null to an ArrayList?

    I am asking this question because in a project we had a bug where some code was adding null to the ArrayList and it was hard to spot where the bug was. Obviously a NullPointerException was thrown but not until other code tried to access the element. The problem was how to locate the code that added the null object. It would have been easier if ArrayList threw an exception in the code where the elements was being added.

    The Guava Project has a pretty interesting page on that topic (they don't allow `null` in most of their collections).

    I believe that the answers given here cover well the question. Maybe one thing that should be mentioned is: don't take everything that's in the JDK as holly and perfect, and then whack your head trying to understand why it is so "perfect". Some things are (honest, IMHO) mistakes, that remained there due to backwards compatibility and that's that. Even the Java creators admit it, just read Joshua Bloch's books to see his critique of certain Java APIs. At any rate, your question comes down to weather there isn't a more elegant way to catch NPE in Java. The answer is, no, but there should be.

    Can you provide more information on why it should not be allowed? If it is just a matter of taste, then the less restrictive should be prefered.

    The simple answer is just that `null` is the default way to represent missing data in Java, whether you like it or not. In fact a lot of people don't like it and make it an argument for functional programming-style things. The most upvoted answer makes no sense/doesn't capture the essence of the issue.

    @JIXiang You're oversimplifying what `null` is. "Missing" is just one of several potential interpretations of `null`. Other valid interpretations could be "Unknown," "Not Applicable," or "Uninitialized." What `null` represents depends on the application. As the Python community would say, "In the face of ambiguity, refuse the temptation to guess." Refusing to hold null in a container that is perfectly capable of doing so would be just that--a guess.

  • gnat

    gnat Correct answer

    8 years ago

    This design decision appears mostly driven by naming.

    Name ArrayList suggests to reader a functionality similar to arrays - and it is natural for Java Collections Framework designers to expect that vast majority of API users will rely on it functioning similar to arrays.

    This in particular, involves treatment of null elements. API user knowing that below works OK:

    array[0] = null; // NPE won't happen here
    

    would be quite surprised to find out if similar code for ArrayList would throw NPE:

    arrayList.set(0, null); // NPE => WTF?
    

    Reasoning like above is presented in JCF tutorial stressing points that suggest close similarity between ArrayList and plain arrays:

    ArrayList... offers constant-time positional access and is just plain fast...

    If you would want a List implementation disallowing nulls, it would better be called like NonNullableArrayList or something like that, to avoid confusing API users.


    Side note there is an auxiliary discussion in comments below, along with additional considerations supporting the reasoning laid out here.

    This explanation is not convincing, considering that `LinkedList` *also* supports `null` list entries.

    @StephenC LinkedList could get this "transitively" so to speak, once designers decided that they want null entries to be supported by particular List implementation, they could push this to other implementations as a matter of consistency. Rephrasing self, "API user knowing that `arrayList.set(0, null)` works OK, would be quite surprised to find out if similar code for LinkedList would throw NPE"

    Yea ... but a simpler and (IMO) more plausible explanation is that allowing `null` entries is useful in a lot of cases.

    ArrayList isn't called like that because it mimics an array. It is called like that because it is a list implemented as an array. Just as a TreeMap doesn't behave like a Tree.

    This answer, IMO, is just plain wrong. Nulls are allowed because in Java, for better or worse, (IMO, worse) null gets used a lot to represent uninitialized or missing values. How did it get the most votes and the "accept" check? Seriously, I'm really losing faith in StackOverflow these days.

    @FlorianF exposing underlying data structure in the name (when done right) sets right expectations of API users. Using your own example, knowing that mapping goes to tree helps to understand "guaranteed log(n) time cost for the containsKey, get, put and remove operations" (javadocs)

    @user949300 nice theory about wide usage of null being the reason, but I guess you didn't post it as an answer because you found nothing to back it up? FWIW I also considered this when doing research before answering, and had to drop exactly for this reason, found nothing to back it up

    @gnat - A quick Google search finds many articles about nulls, including this quote: "A wise man once said you are not a real Java programmer until you've dealt with a null pointer exception. Joking aside, the null reference is the source of _many_ problems." It is undeniable that nulls are commonly used /misused in Java. Or do you want evidence that the designers of Collections specifically allowed nulls because they were common? Can't provide that directly, but I believe they designers of Collections were smart, and might have avoided nulls if they were not so darned common.

    @user949300 correct. I couldn't make a compelling general case for wide usage of null being the reason (if memory serves this was because API docs allow collections rejecting null, and do so without any reservations). Nor could I find that this was the case for ArrayList

    This answer is plain wrong. This is just unsupported guesswork about nulls being allowed in a list implementation. Here is a roundup of Java collections allowing/disallowing nulls; notice how it has *nothing* to do with similarity to arrays.

    @AndresF. re-read the very _roundup_ you refer, it makes a pretty strong connection with arrays with the explanation that `null` is "unavoidable in object arrays". You may call it guesswork as much as you want, but in a collection intended _by name_ to resemble API user behavior of plain arrays, keeping the similarity in treating nulls perfectly fits within principle of least astonishment

    very irrelevant example presented. First of all, who told u that arraylist.set(0,null) throws Runtime Ex because you are trying to set a null value at an index? Runtime Ex is thrown because set() works only for existing indexes, and you may have tried to set on an arraylist which doesn't have any value at index 0 yet. add() and set() are different methods, and set() cannot substitute add() functionality. In case of arrays, assignments are ambiguous, means it doesn't matter you are adding a new value or overwriting existing one. The example provided has no relevance to the question.

    many (almost all) of the prior comments were useful and I addressed all of them. The only comment I didn't address is the last one and this is because I couldn't make any sense of it no matter how I tried

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM