java.util.Arrays$ArrayList addAll报错

执行下面代码时报错:

List<String> centerList = WebConstants.SUPPORT_BIG_CENTERS_LIST;   // WebConstants.SUPPORT_BIG_CENTERS_LIST 是 Arrays.asList 转化来的
centerList.removeAll(WebConstants.SUPPORT_CENTERS_LIST); centerList.addAll(WebConstants.SUPPORT_CENTERS_LIST);

最后一行报错:

java.lang.UnsupportedOperationException: null
    at java.util.AbstractList.add(AbstractList.java:148) ~[na:1.8.0_101]
    at java.util.AbstractList.add(AbstractList.java:108) ~[na:1.8.0_101]
    at java.util.AbstractCollection.addAll(AbstractCollection.java:344)~[na:1.8.0_101]

查看 Arrays$ArrayList 的源代码,如下 (1.8 版本):

private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;
    ArrayList(E[] array) {
        a </span>=<span style="color: rgba(0, 0, 0, 1)"> Objects.requireNonNull(array);
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> size() {
        </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> a.length;
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Object[] toArray() {
        </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> a.clone();
    }

    @Override
    @SuppressWarnings(</span>"unchecked"<span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> &lt;T&gt;<span style="color: rgba(0, 0, 0, 1)"> T[] toArray(T[] a) {
        </span><span style="color: rgba(0, 0, 255, 1)">int</span> size =<span style="color: rgba(0, 0, 0, 1)"> size();
        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (a.length &lt;<span style="color: rgba(0, 0, 0, 1)"> size)
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> Arrays.copyOf(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.a, size,
                                 (Class</span>&lt;? <span style="color: rgba(0, 0, 255, 1)">extends</span> T[]&gt;<span style="color: rgba(0, 0, 0, 1)">) a.getClass());
        System.arraycopy(</span><span style="color: rgba(0, 0, 255, 1)">this</span>.a, 0, a, 0<span style="color: rgba(0, 0, 0, 1)">, size);
        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (a.length &gt;<span style="color: rgba(0, 0, 0, 1)"> size)
            a[size] </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
        </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> a;
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> E get(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> index) {
        </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> a[index];
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> E set(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> index, E element) {
        E oldValue </span>=<span style="color: rgba(0, 0, 0, 1)"> a[index];
        a[index] </span>=<span style="color: rgba(0, 0, 0, 1)"> element;
        </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> oldValue;
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> indexOf(Object o) {
        E[] a </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.a;
        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (o == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; a.length; i++<span style="color: rgba(0, 0, 0, 1)">)
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (a[i] == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
                    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> i;
        } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
            </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; a.length; i++<span style="color: rgba(0, 0, 0, 1)">)
                </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (o.equals(a[i]))
                    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> i;
        }
        </span><span style="color: rgba(0, 0, 255, 1)">return</span> -1<span style="color: rgba(0, 0, 0, 1)">;
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> contains(Object o) {
        </span><span style="color: rgba(0, 0, 255, 1)">return</span> indexOf(o) != -1<span style="color: rgba(0, 0, 0, 1)">;
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> Spliterator&lt;E&gt;<span style="color: rgba(0, 0, 0, 1)"> spliterator() {
        </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Spliterators.spliterator(a, Spliterator.ORDERED);
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> forEach(Consumer&lt;? <span style="color: rgba(0, 0, 255, 1)">super</span> E&gt;<span style="color: rgba(0, 0, 0, 1)"> action) {
        Objects.requireNonNull(action);
        </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (E e : a) {
            action.accept(e);
        }
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> replaceAll(UnaryOperator&lt;E&gt;<span style="color: rgba(0, 0, 0, 1)"> operator) {
        Objects.requireNonNull(operator);
        E[] a </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.a;
        </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; a.length; i++<span style="color: rgba(0, 0, 0, 1)">) {
            a[i] </span>=<span style="color: rgba(0, 0, 0, 1)"> operator.apply(a[i]);
        }
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> sort(Comparator&lt;? <span style="color: rgba(0, 0, 255, 1)">super</span> E&gt;<span style="color: rgba(0, 0, 0, 1)"> c) {
        Arrays.sort(a, c);
    }
}</span></pre>

进入父类找下 addAll 方法:

public boolean addAll(int index, Collection<? extends E> c) {rangeCheckForAdd(index);
        boolean modified = false;
        for (E e : c) {
            add(index++, e);
            modified = true;
        }
        return modified;
    }

实现只存在于父类中,如下所示:

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

父类AbstractList add 方法直接抛出异常。

所以问题就在这里,我们改下代码,如下就不报错了:

List<String> centerList = new ArrayList<>();

if (null != WebConstants.SUPPORT_BIG_CENTERS_LIST) {  //addAll 的目标是 null 会报错
centerList.addAll(WebConstants.SUPPORT_BIG_CENTERS_LIST);
}
if (null != WebConstants.SUPPORT_CENTERS_LIST) {
centerList.removeAll(WebConstants.SUPPORT_CENTERS_LIST);
centerList.addAll(WebConstants.SUPPORT_CENTERS_LIST);
}

它调用的就是 arrayList 的 addAll 方法了