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

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


我正在通过HashSet's javadocs 搜索它的实现规范,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()


海绵宝宝撒
浏览 92回答 2
2回答

阿波罗的战车

不,这只是多态性。每当在对象上调用方法时,该对象的真实类型很重要,仅此而已。foo()含义:在 Base 中实现并不重要。当在 Child 中被覆盖时foo()调用。当你有一个 Child 对象时,它总是会被调用的 Child 版本。bar()bar()bar()在您的示例中,this不是 AbstractSet,它是HashSet!或者换句话说:调用方法的“位置”并不重要。重要的是调用它的对象的类型。如前所述,您的对象是 HashSet 类型!

慕码人8056858

这是个有趣的问题。HashSet在 Java 中由HashMap.&nbsp;该containsAll()方法只是contains()在这种情况下HashSet的 contains 方法中循环。那是因为HashSet覆盖了contains和委托。因为HashSet由HashMap实际调用支持 is&nbsp;containsKey(Object key)。'&nbsp;HashMapscontainsKey(Object key)主要是给你O(1)复杂性。但是,containsAll()确实会遍历n元素。您的最坏情况复杂性变为O(n).我之所以说它主要是因为 a 的性能HashMap依赖于散列。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java