当超类型方法调用超类型和子类型中存在的方法时,调用哪个实例方法

Gar*_*kai 5 java inheritance

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

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

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

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

public boolean contains(Object o) {
    return map.containsKey(o);
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

我的理解一直是当一个实例成员调用不明确实例中指定时,JVM隐含代替它this.instanceMemberCall(),在这种情况下,将转化成AbstractCollectioncontains()被调用.但是,有一次我读到这里,对于时间复杂度HashMap/ HashSetcontainsAll()是O(n)的暗示HashSetcontains()(O(1))被调用.将会明白这背后的实际语义是什么.

Gho*_*ica 3

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

含义:在 Base 中实现并不重要foo()。当foo()调用bar()bar()Child 覆盖时。bar()当您有一个 Child 对象时,调用的将始终是 Child版本。

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

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