问题:在应用一个Collection.addAll()办法时报告UnsupportedOperationException。追溯起因发现该collection是来自于hashMap.values()。

剖析起因:通过查看源代码,发现hashMap.values()实现如下:

//HashMap.java
public Collection<V> values() {

    Collection<V> vs = values;    return (vs != null ? vs : (values = new Values()));}  private final class Values extends AbstractCollection<V> {    public Iterator<V> iterator() {        return newValueIterator();    }    public int size() {        return size;    }    public boolean contains(Object o) {        return containsValue(o);    }    public void clear() {        HashMap.this.clear();    }}//其中values的定义如下:AbstractMap.java  transient volatile Collection<V> values = null;   public Collection<V> values() {    if (values == null) {        values = new AbstractCollection<V>() {            public Iterator<V> iterator() {                return new Iterator<V>() {                    private Iterator<Entry<K,V>> i = entrySet().iterator();                    public boolean hasNext() {                        return i.hasNext();                    }                    public V next() {                        return i.next().getValue();                    }                    public void remove() {                        i.remove();                    }                };            }            public int size() {                return AbstractMap.this.size();            }            public boolean isEmpty() {                return AbstractMap.this.isEmpty();            }            public void clear() {                AbstractMap.this.clear();            }            public boolean contains(Object v) {                return AbstractMap.this.containsValue(v);            }        };    }    return values;}

从下面代码看到,hashMap.values()先看values是否为空:

如果不为空,则间接返回values。values是在在AbstractMap中定义的,初始化时new了一个AbstractCollection,并实现了若干办法,然而并没有实现all()和addAll()办法。

如果为空,则new一个外部实现类Values。Values同样没有实现AbstractCollection的没有实现all()和addAll()办法。

再来看一下AbstractCollection的add()和addAll()办法:

//AbstractCollection.java
public boolean add(E e) {

    throw new UnsupportedOperationException();}

public boolean addAll(Collection<? extends E> c) {

    boolean modified = false;    for (E e : c)        if (add(e))            modified = true;    return modified;}

能够看到,add办法的实现是间接抛出UnsupportedOperationException,addAll办法调用add办法,也间接抛出异样,同样的,HashMap.values()调用add()和addAll()也会抛出异样。

论断:通过以上剖析,明确了HashMap.values()调用add()和addAll()抛出异样的起因。也通知咱们在理论应用中,要留神防止间接应用HashMap.values().add()和HashMap.values().addAll()。
另外:HashMap.vKeySet(),HashMap.entrySet()调用add()和addAll()办法也是如此。