43

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.

7
  • 12
    The Guava Project has a pretty interesting page on that topic (they don't allow null in most of their collections). Commented Sep 3, 2012 at 15:09
  • 6
    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. Commented Sep 3, 2012 at 15:13
  • 2
    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. Commented Jul 16, 2014 at 10:54
  • 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.
    – xji
    Commented Apr 12, 2016 at 4:22
  • @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.
    – riwalk
    Commented Apr 3, 2018 at 19:30

8 Answers 8

38

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.

13
  • 12
    This explanation is not convincing, considering that LinkedList also supports null list entries.
    – Stephen C
    Commented Jul 16, 2014 at 11:50
  • 12
    Yea ... but a simpler and (IMO) more plausible explanation is that allowing null entries is useful in a lot of cases.
    – Stephen C
    Commented Jul 21, 2014 at 22:48
  • 7
    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.
    – Florian F
    Commented Sep 14, 2014 at 6:38
  • 12
    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.
    – user949300
    Commented Sep 15, 2014 at 18:13
  • 9
    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.
    – Andres F.
    Commented Oct 9, 2014 at 12:37
33

Null may be a valid value for an element of a list. Say your list contains elements which represent some optional data about a list of users and is stored in the same order as the users. If the extra data is populated then your list will contain the additional data otherwise the slot corresponding to a user will be null. (I'm sure there are better examples, but you get the idea)

if you don't want to allow nulls to be added then you could wrap the array list with your own wrapper which threw when null was added.

6
  • 2
    That seems like a bad example of why nulls should be allowed -- there's better ways of representing optional data than using null values in a list.
    – casablanca
    Commented Sep 4, 2012 at 3:34
  • @casablanca yeah totally agree, its not a great example.
    – Sam Holder
    Commented Sep 4, 2012 at 7:26
  • I can't find a good reason for a ArrayList to contain nulls, other then bad surprises for the next developer to 'discover' it :/ Commented Sep 4, 2012 at 10:58
  • 7
    @casablanca While I agree with you that nulls should be avoided for representing optional data, in Java, for better or worse, that is "traditional".
    – user949300
    Commented Sep 15, 2014 at 18:16
  • 2
    A solid use-case: You want to pass the parameters to some dynamic function as a list. You have several functions, each with a different set of parameters, so you need a dynamically sized array and you can always pass null as a valid function argument!
    – Falco
    Commented Jan 13, 2015 at 13:39
21

ArrayList allows null by design. It is intentional. From the javadoc:

"[ArrayList is a] resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null."

The answer to "why" is that if it didn't the ArrayList wouldn't be usable in cases where it is necessary to put a null in the list. By contrast, you can prevent an ArrayList from containing nulls by either testing values before adding them or using a wrapper that prevents this happening.

Is there any case where I would want to add null to an ArrayList?

Obviously, any case where null has a distinct meaning. For instance it might mean that the value at a given position in the list has not been initialized or supplied.

It would have been easier if the ArrayList had thrown an exception in the code where the elements was being added.

You could easily implement that behaviour by creating a wrapper class. However, this is not the behaviour that most programmers / applications need.

0
8

Is there any case where I would want to add null to an ArrayList?

Sure, what about pre-allocation? You want an ArrayList of things you can't create yet because you don't have enough info. Just because you can't think of a reason why someone may want to do something doesn't make it a bad idea. Whatever. (Now, I'm sure someone will come along and say you should instead have empty objects that fulfill some pattern they read about on some obscure blog and that programmers should really be able to write programs without ever using if statements, blah blah.)

If you guys have a contract that there never should be nulls in a container then it's up to you lot to make sure that contract is upheld, probably most appropriately by asserting. It would probably have taken you max 10 lines of code. Java makes it incredibly easy for you to do this sort of thing. The JDK cannot read your mind.

9
  • 1
    Your preallocation argument is invalid, because this is already build into ArrayList with the ensureCapacity(int minCapacity) method and the ArrayList(int initialCapacity) constructor.
    – Philipp
    Commented Sep 15, 2014 at 15:10
  • 7
    @Philipp What values will it put into that space?
    – James
    Commented Sep 15, 2014 at 17:25
  • The obvious choice is to put a null in the pre-allocated (but as yet unused) entries of the ArrayList; but we can let ensureCapacity do that and yet not allow other functions such as set to do it. The reasons given elsewhere seem stronger.
    – David K
    Commented Oct 9, 2014 at 12:45
  • @DavidK: It makes sense to say that it should be possible to set an item to any value which could be returned by get. Even if a normal attempt to get an item for which space had been allocated but never written should throw an exception rather than returning null, it would still be useful to have a pair of methods that would allow list1.setOrEraseIfNull(index, list2.getOrReturnNull(index)) rather than requiring if (list2.valueSet(index)) list1.set(index, list2.get(index)); else list1.unset(index);
    – supercat
    Commented Oct 13, 2014 at 19:07
  • 1
    @DavidK: Attempting to read an entry which has been allocated but not yet written must either yield null or throw an exception; it's easier to have it return null.
    – supercat
    Commented Oct 14, 2014 at 1:58
4

This seems to be more of a (software-)philosophic question here.

ArrayList as a utility class is designed to be helpful in a wide context of possible use-cases.

Contrary to your hidden claim that accepting null as a valid value should be discouraged, there are many examples where the null value is perfectly legal.

The single most important reason is that null is the do not know equivalent of any reference type, including framework types. This implies that null cannot be replaced in any case by a more fluent version of the nothing value.

So, lets say you store the Integers 1, 3, 7 in your arraylist at its corresponding index: Due to some computation, you want to get the element at index 5, so what your array should return is: "no value stored". This could be achieved through returning null or a NullObject. In most cases returning the built in null value is expressive enough. After calling a method that can return null and using its return value a check of the returned value against null is quite common in modern code.

4

The statement

File f = null;

is valid and useful (I don't think I need to explain why). It is likewise useful to have a collection of files, some of which may be null.

List<File> files = new ArrayList<File>();
// use my collection of files
// ....
// not using this one anymore:
files.set(3, null);

The usefulness of collections that may contain null objects proceeds directly from the usefulness of objects that may be null. It is really as simple as that.

0
2

It is easier to accept everything, than to be to be restrictive and then try opening up your design after the fact.

For example, what if they oracle/sun provided only NonNullableArrayList, but you wanted to be able to add a Null to your list. How would you do it? You would probably have to create an entirely different object, you couldn't use extend the NonNullableArrayList. Instead if you have a ArrayList that takes everything, you could easily extend it, and override the add, where it doesn't accept null values.

2
  • 2
    Disagreed. Allowing too much is harder to correct once the misfeature has seen widespread use. If language designers allowed nulls at a later stage, it wouldn't break existing programs, but the opposite is not true.
    – Andres F.
    Commented Sep 3, 2012 at 16:49
  • 2
    But I agree. It is about maximizing functionality. You can use a list that accepts nulls even you don't need them. You cannot use a list that refuses nulls if you need nulls.
    – Florian F
    Commented Sep 14, 2014 at 7:01
-1

Usefullness of null?

Very much so when you go with a List of Lists to model a 2D real life plate with different positions. Half of those positions could be empty (in random coordinates) while the filled ones don't represent a simple int or String but are represented by a complex object. If you want to keep the positional info, you need to fill the empty spots with null so that your list.get(x).get(y) doesn't lead to nasty surprises. To counter the null exceptions you can check for null (very popular) or you can use an Optional (which I find handy in this case). The alternative would be to fill the empty spots with "junk" objects which can lead to all kinds of mess down the road. If your null check fails or is forgotten somewhere, Java will let you know. On the other hand a "junk" placeholder object which is not checked properly may pass unnoticed.

Not the answer you're looking for? Browse other questions tagged or ask your own question.