Immutable empty collections and iterators

Have you ever wondered why the java.util.Collections class includes various "empty" class methods, which return immutable empty collections and immutable empty iterators This post answers this question.

The Collections class's various "empty" class methods offer a useful alternative to returning null (and avoiding potential java.lang.NullPointerExceptions from being thrown) in certain contexts. Listing 1 presents the source code to an application that demonstrates the benefit of an immutable empty list.

Listing 1 declares a Flowers class that stores the names of various flowers in a list. This class provides two constructors: a noargument constructor and a constructor that takes a variable number of java.lang.String arguments identifying various flowers.

The noargument constructor invokes <T> List<T> emptyList() to initialize its private flowers field to an empty java.util.List of String -- emptyList() is a generic method and the compiler infers its return type from its context.

If you're wondering about the need for emptyList(), examine the toString() method. Notice that this method evaluates flowers.toString(). If you didn't assign a reference to an empty List<String> to flowers, flowers would contain the null reference (the default value for this instance field when the object is created), and a NullPointerException object would be thrown when attempting to evaluate flowers.toString().

Compile Listing 1 as follows:

Run the resulting application as follows:

You should observe the following output:

Most of the "empty" methods return immutable empty collections, but three methods return immutable empty iterators: <T> Enumeration<T> emptyEnumeration() (classic iteration method), <T> Iterator<T> emptyIterator(), and <T> ListIterator<T> emptyListIterator(). Listing 2 demonstrates the need for an immutable empty iterator.

Listing 2 presents ToDo and ToDoList classes that describe individual and lists of to-do tasks in terms of task name and date by which the task should have been performed. ToDoList's add() method lazily initializes the list. Unfortunately, this lazy initialization can result in a thrown NullPointerException object.

NullPointerException arises when toDoList.iterator() in ToDoList's iterator() method is executed and toDoList contains the null reference because add() hasn't been called. Compiling Listing 2 (javac and running the application (java EmptyIteratorDemo) results in the following output:

You can avoid the exception by uncommenting the toDoList.add() call in the main() method. Better still, you can modify ToDoList's iterator() method to return the result of calling Collections.emptyIterator() when toDoList contains the null reference, as follows:

The Collections class's various "empty" class methods can help you write safer code that avoids thrown NullPointerExceptions. They can also help you write more streamlined code because you don't always have to test for null references. For example, Listing 1's toString() method specifies return flowers.toString(); instead of having to specify the longer return (flowers != null) flowers.toString() : "";.


Jeff Friesen

Zur Startseite