V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
amiwrong123
V2EX  ›  Java

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

  •  
  •   amiwrong123 · 2019-11-09 22:02:45 +08:00 · 2564 次点击
    这是一个创建于 1844 天前的主题,其中的信息可能已经有所发展或是发生改变。
    //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方法也有同样疑问。

    2 条回复    2019-11-15 13:21:29 +08:00
    cxtrinityy
        1
    cxtrinityy  
       2019-11-10 21:26:48 +08:00
    如果 AbstractMap 的实现类重写了 isEmpty 呢
    amiwrong123
        2
    amiwrong123  
    OP
       2019-11-15 13:21:29 +08:00 via Android
    @cxtrinityy 你说的对啊,如果重写了,而且实现逻辑还不是 size()==0,那就必须调用到 AbstractMap 的实现上了。因为 keyset 要依赖外部类。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3904 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 00:55 · PVG 08:55 · LAX 16:55 · JFK 19:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.