//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
方法也有同样疑问。
1
cxtrinityy 2019-11-10 21:26:48 +08:00
如果 AbstractMap 的实现类重写了 isEmpty 呢
|
2
amiwrong123 OP @cxtrinityy 你说的对啊,如果重写了,而且实现逻辑还不是 size()==0,那就必须调用到 AbstractMap 的实现上了。因为 keyset 要依赖外部类。
|