为毛 AbstractMap 的 keySet 方法里面的 AbstractSet 匿名内部类要重写 isEmpty 方法啊?

2019-11-09 22:02:45 +08:00
 amiwrong123
//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方法也有同样疑问。

2496 次点击
所在节点    Java
2 条回复
cxtrinityy
2019-11-10 21:26:48 +08:00
如果 AbstractMap 的实现类重写了 isEmpty 呢
amiwrong123
2019-11-15 13:21:29 +08:00
@cxtrinityy 你说的对啊,如果重写了,而且实现逻辑还不是 size()==0,那就必须调用到 AbstractMap 的实现上了。因为 keyset 要依赖外部类。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/618007

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX