问题:在使用一个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()。
时间: 2024-10-29 19:06:14