首页 > 解决方案 > 当超类型方法调用超类型和子类型中都存在的方法时调用哪个实例方法

问题描述

如果我在这里遗漏了一些核心 Java,请原谅我。

我正在通过HashSetjavadocs 搜索它的实现规范,Collection.containsAll()它显然继承了AbstractCollection根据JDK 8 源代码文档的实现,如下所示:

public boolean containsAll(Collection<?> c) {
    for (Object e : c)
        if (!contains(e))
            return false;
    return true;
}

我的问题源于这样一个事实,即虽然HashSet不会覆盖containsAll()它但是会覆盖contains()

public boolean contains(Object o) {
    return map.containsKey(o);
}

AbstractCollection同样地:

public boolean contains(Object o) {
    Iterator<E> it = iterator();
    if (o==null) {
        while (it.hasNext())
            if (it.next()==null)
                return true;
    } else {
        while (it.hasNext())
            if (o.equals(it.next()))
                return true;
    }
    return false;
}

我的理解是,当实例成员调用未在实例中显式指定时,JVM 会隐式替换它this.instanceMemberCall(),在这种情况下将转换为AbstractCollection'contains()被调用。但是我再次在这里读到HashMap/的时间复杂度将是 O(n),这表明's HashSet( O(1)) 被调用。希望能清楚地了解这背后的实际语义是什么。containsAll()HashSetcontains()

标签: javainheritance

解决方案


不,这只是多态性。每当在对象上调用方法时,该对象的真实类型很重要,仅此而已。

foo()含义:在 Base 中实现并不重要。当在 Child 中被覆盖时foo()调用。当你有一个 Child 对象时,它总是会被调用的 Child 版本。bar()bar()bar()

在您的示例中,this不是 AbstractSet,它是HashSet

或者换句话说:调用方法的“位置”并不重要。重要的是调用它的对象的类型。如前所述,您的对象是 HashSet 类型!


推荐阅读