//AbstractMap.java file
//省略
transient Set<K> keySet;
transient Collection<V> values;
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new AbstractSet<K>() {//AbstractSet 的匿名内部类
public Iterator<K> iterator() {
return new Iterator<K>() {
private Iterator<Entry<K,V>> i = entrySet().iterator();
public boolean hasNext() {
return i.hasNext();
}
public K next() {
return i.next().getKey();
}
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 k) {
return AbstractMap.this.containsKey(k);
}
};
keySet = ks;
}
return ks;
}
//省略
先简单说一下把,这里 keySet()方法设计成了一种类似于单例模式的情况,这个单例是 AbstractSet 的匿名内部类,在 java 编程思想中 17.2.3 使用 Abstract 类小节能够看到,继承 AbstractSet 实际上只需要实现size() & iterator()
方法即可。
但 AbstractMap 源码这里它还重写了 isEmpty()方法,AbstractSet 的类定义是这样的public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E>
,isEmpty()
方法实际上已经在AbstractCollection
里面实现好了:public boolean isEmpty() { return size() == 0; }
,而 AbstractMap 也实现了isEmpty()
方法,实现逻辑也是public boolean isEmpty() { return size() == 0; }
那么我觉得 AbstractSet 的匿名内部类不需要重写isEmpty()
方法了啊,你看它的逻辑是public boolean isEmpty() { return AbstractMap.this.isEmpty(); }
,它只是想调用持有的外部类 map 对象的isEmpty()
方法,但 AbstractMap 的isEmpty()
方法和 AbstractCollection 的isEmpty()
方法根本一样啊,那重写也没有必要了啊。
进一步说,AbstractSet 的匿名内部类不管重不重写isEmpty()
方法,最终实际调用到的都是重写后的size()
方法啊。
而且同样的,对于 AbstractSet 的匿名内部类重写clear
方法也有同样疑问。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.