一、Collections.emptyList()集合中使用add()保存元素,报异常 java.lang.UnsupportedOperationException分析

1、保存元素抛出异常:java.lang.UnsupportedOperationException

2、原因是Collections.emptyList()内部空集合没有实现AbstractList<T>中的add(int, E)函数导致报异常,AbstractList中的add(int, E)函数为抛出异常实现,如下所示,需要在使用中进行覆写操作,在ArrayList中进行了覆写实现。

AbstractList源代码中的add(int,E)实现
/**
 * {@inheritDoc}
 *
 * <p>This implementation always throws an
 * {@code UnsupportedOperationException}.
 *
 * @throws UnsupportedOperationException {@inheritDoc}
 * @throws ClassCastException            {@inheritDoc}
 * @throws NullPointerException          {@inheritDoc}
 * @throws IllegalArgumentException      {@inheritDoc}
 * @throws IndexOutOfBoundsException     {@inheritDoc}
 */
public void add(int index, E element) {
   throw new UnsupportedOperationException();
}

ArrayList源代码中的add(int,E)实现
/**
 * Inserts the specified element at the specified position in this
 * list. Shifts the element currently at that position (if any) and
 * any subsequent elements to the right (adds one to their indices).
 *
 * @param index index at which the specified element is to be inserted
 * @param element element to be inserted
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public void add(int index, E element) {
    rangeCheckForAdd(index);

    ensureCapacityInternal(size + 1);  // Increments modCount!!
    System.arraycopy(elementData, index, elementData, index + 1,
                      size - index);
    elementData[index] = element;
    size++;
}

二、Collections中的EmptyList<T>内部类实现源代码,可以发现没有对add(int,E)进行实现:

    /**
     * @serial include
     */
    private static class EmptyList<E>
        extends AbstractList<E>
        implements RandomAccess, Serializable {
        private static final long serialVersionUID = 8842843931221139166L;

        public Iterator<E> iterator() {
            return emptyIterator();
        }
        public ListIterator<E> listIterator() {
            return emptyListIterator();
        }

        public int size() {return 0;}
        public boolean isEmpty() {return true;}

        public boolean contains(Object obj) {return false;}
        public boolean containsAll(Collection<?> c) { return c.isEmpty(); }

        public Object[] toArray() { return new Object[0]; }

        public <T> T[] toArray(T[] a) {
            if (a.length > 0)
                a[0] = null;
            return a;
        }

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

        public boolean equals(Object o) {
            return (o instanceof List) && ((List<?>)o).isEmpty();
        }

        public int hashCode() { return 1; }

        @Override
        public boolean removeIf(Predicate<? super E> filter) {
            Objects.requireNonNull(filter);
            return false;
        }
        @Override
        public void replaceAll(UnaryOperator<E> operator) {
            Objects.requireNonNull(operator);
        }
        @Override
        public void sort(Comparator<? super E> c) {
        }

        // Override default methods in Collection
        @Override
        public void forEach(Consumer<? super E> action) {
            Objects.requireNonNull(action);
        }

        @Override
        public Spliterator<E> spliterator() { return Spliterators.emptySpliterator(); }

        // Preserves singleton property
        private Object readResolve() {
            return EMPTY_LIST;
        }
    }

三、复现异常代码如下:

/**
 * 复现Collections.emptyList()保存元素异常
 * java.lang.UnsupportedOperationException
 * @author fengbin15
 */
public class CollectionEmptyListTest {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//Collections.emptyList()
		List<String> strEmptyList = Collections.emptyList();
		//向Collections.emptyList()中添加元素,报异常,
		//原因是Collections.emptyList()没有覆写AbstractList中的add(int, E)函数
		strEmptyList.add("a");
	}
}

 

四、从Collections.emptyList()推测和进一步确认,常用的emptyMap()和emptySet()也不能直接保存元素,只可用来保证避免空指针异常。

 

     以上为个人经验总结,供参考,有不恰当的地方,劳烦指正,共同进步,谢谢!

 

 

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐