Java Collections emptyList EMPTY_LIST Detailed Explanation and Use Instructions

  • 2021-12-12 04:37:03
  • OfStack

Use Collections. emptyList () for emptyList, EMPTY_LIST of Collections

emptyList, EMPTY_LIST for Collections

Today, when looking at the code written by the big brother, when the result set is empty, what he returns is not null, but:


return Collections.EMPTY_LIST;

We all know that returning null is very likely to cause a null pointer exception. You can use emptyList or EMPTY_LIST to avoid this problem unless you want to capture this null information

When we use the emptyList null method to return an empty collection, we should pay attention to the fact that this empty collection is immutable.

Empty collection can not use add method, will report UnsupportedOperationException exception, see the following source code:


    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }

Empty collection object can not use put method, will report IndexOutOfBoundsException exception, see the following source code:


 public E get(int index) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }

However, no exception occurs for the for loop, as shown in the following example:


 List<String> list1 = Collections.emptyList();
        for(String s:list1) {
        }
        for(int i=0;i<list1.size();i++) {
        }

The above two for loops can be executed normally, and the first foreach loop will become iterator mode after actual compilation, so that we can understand why it can be executed normally; The second is that only the size method is called, and we can see that the source code directly returns 0;


public int size() {return 0;}

The difference between emptyList and EMPTY_LIST, let's look at the source code:


    /**
     * The empty list (immutable).  This list is serializable.
     *
     * @see #emptyList()
     */
    @SuppressWarnings("unchecked")
    public static final List EMPTY_LIST = new EmptyList<>();

/**
     * Returns the empty list (immutable).  This list is serializable.
     *
     * <p>This example illustrates the type-safe way to obtain an empty list:
     * <pre>
     *     List&lt;String&gt; s = Collections.emptyList();
     * </pre>
     * Implementation note:  Implementations of this method need not
     * create a separate <tt>List</tt> object for each call.   Using this
     * method is likely to have comparable cost to using the like-named
     * field.  (Unlike this method, the field does not provide type safety.)
     *
     * @see #EMPTY_LIST
     * @since 1.5
     */
    @SuppressWarnings("unchecked")
    public static final <T> List<T> emptyList() {
        return (List<T>) EMPTY_LIST;
    }

We see that EMPTY_LIST is a static constant of the Collections class, and emptyList supports generics. EMPTY_LIST can be used directly where generics are not required, and emptyList is required where generics are required.

Through the above analysis, we can clearly know when to use emptyList;; There are several other empty sets in the Collections set, emptyMap and emptySet, which are used in much the same way as above.

Collections. emptyList ()

Accidentally found that a small partner used the Collections. emptyList () method incorrectly, record 1 here. It is used in the following ways:


public void run() {
    ......
    List list = buildList(param);
    ......
    Object newNode = getNode(...);
    list.add(newNode);
    ......
}
 
public List buildList(Object param) {
    if (isInValid(param)) {
        return Collections.emptyList();
    } else {
        ......
    }
}

An "empty List" may be returned in the buildList method, and elements may be added (or removed) to this List later, but it is not noted that Collections. The emptyList method returns an EMPTY_LIST:


public static final <T> List<T> emptyList() {
    return (List<T>) EMPTY_LIST;
}

It is an static final modified member variable and an instance of the EmptyList class:


public static final List EMPTY_LIST = new EmptyList<>();

This EmptyList is a static inner class and inherits from AbstractList like ArrayList1:


    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
0

You can see that this EmptList does not override the add method, and the get method directly throws an IndexOutOfBoundsException exception. Since the add method is not overridden, look at the add method in the parent class AbstractList:


    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
1

You can see the UnsupportedOperationException exception thrown directly. Going back to the EmptyList class, the methods it provides externally also obviously limit its scope of use.

For Collections.emptyList (), or Collections.EMPTY_LIST, it is best to only regard it as the identification of an empty list (it can be imagined as an empty List that has passed frozen), and do not add, delete and check it. If some branch logic in the program returns this instance and is not covered during the test, if you go to this branch logic in the production environment, it will be troublesome ~


Related articles: