在不覆盖方法时使用 super.method() ?

Using super.method() when you're not overriding the method?

是否总是使用 super 从超类调用方法,即使我没有重写该方法?

假设

public class Parent{
    public void method() {

    }
}

所以

public class Child extends Parent {
    public void someMethod() {
        super.method();
    }
}

public class Child extends Parent {
    public void someMethod() {
        method();
    }
}   

感谢您的意见。

调用 super 告诉 JVM 显式 查看方法的父 class 版本。继续你的例子,如果你只是调用

method()

JVM 将首先在调用 class 中搜索方法(在本例中为 Child),然后再查看父 class。另一方面,如果您调用

super.method()

那么 JVM 将显式地查看父 class 的实现,即使 Child 有一个名为 method() 的方法。

将这两个想法放在一起,当您打算调用父 class 方法时,您可能应该始终使用 super。如果您的 class 没有覆盖该方法,那么您 可以 调用而无需 super。但是,如果有人稍后重构您的 class 并覆盖该方法,即使这样也会成为问题。

Is it common practice to always use super for calling methods out of the superclass? Or is it redundant code?

这不是多余的。它有一个调用 parent class 方法的特殊目的(虽然你 ovveriden)。当你不想的时候,不要调用。如果您当前的 class 不是那个 class 的 child,super 将不适合您。

Also if you call an overridden supermethod, does it use the supermethod or the lowest method?(in the inheritance tree)

重写的方法。由于您在 class.

中覆盖了它

是否调用 super 方法完全取决于您要做什么。如果你想做 parent class 做的事情再加上一些额外的动作,那么调用 super 方法是好的。如果您在 child 实现中做一些完全不同的事情,那么不要调用 super 方法。当您在 classes 的层次结构中调用 super 方法时,它会调用层次结构中最接近您的 child class 的方法。

在某些情况下,您可能有一个 API,其中调用 super 方法是整个契约的一部分。 clone方法就是这种情况。

如果 Child 与 Parent 具有相同的版本方法,如果没有 "super",JVM 将调用 Child 的版本而不是 Parent 的版本。如果您想确保子项始终调用父项的版本方法,"super" 关键字很有用。

引导题很容易回答:

Is it common practice to always use super for calling methods out of the superclass, even when I'm NOT overriding the method?

不,这不是常见的做法。相反,这样做 会造成危险的混乱 。您可以正常调用方法,因为继承的要点是允许 类 覆盖方法以 change/extend 它们的行为。您通常不关心方法实际实现的级别。

明显的例外是当您 do 自己重写该方法并且您 want/need parents 功能.

现在进入显式调用 super 的危险混乱 部分:

public class CallSuper {

    static class Parent {
        public void foo() {
            System.out.println("Parent.foo");
        }

        /** 
         * Calls foo to do the main work
         */
        public void bar() {
            System.out.print
            foo();
        }
    }

    static class Child extends Parent {
        public void foo() {
            System.out.println("Child.foo");
        }

        public void bar() {
            super.foo();
        }
    }

    static class GrandChild extends Child {
        public void foo() {
            System.out.println("GrandChild.foo");
        }
    }

    public static void main(String[] args) {
        Parent p = new Parent();
        Parent c = new Child();
        Parent g = new GrandChild();

        System.out.print("Parent.foo() = ");
        p.foo();
        System.out.print("Child.foo() = ");
        c.foo();
        System.out.print("GrandChild.foo() = ");
        g.foo();

        System.out.print("Parent.bar() = ");
        p.bar();
        System.out.print("Child.bar() = ");
        c.bar();
        System.out.print("GrandChild.bar() = ");
        g.bar();
    }
}

如果你运行这个例子它会输出(为清楚起见添加行号):

1 Parent.foo() = Parent.foo
2 Child.foo() = Child.foo
3 GrandChild.foo() = GrandChild.foo
4 Parent.bar() = Parent.foo
5 Child.bar() = Parent.foo
6 GrandChild.bar() = Parent.foo

前四行不出奇,我们得到foo在每一层分别实现了什么,分别是Parents的bar调用它的foo。它在第 5 行开始变得奇怪。Child 通过调用 super.bar() 绕过了它自己对 foo 的覆盖,所以虽然它的 foo() 是专门的,但 bar() 不是。在第 6 行中,您看到 GrandChild 从 Child 继承了这个奇怪的东西,所以 Child 的栏中看起来有点无辜的 super.foo() 现在已经破坏了 GrandChild 期望其对 foo() 的覆盖对所有 bar() 也有效。

现在,如果您想象 foo() 和 bar() 实际上在做一些 有用的事情,并且它们之间存在有意义的关系,例如您会相信(通过 Parent 的文档或常识)覆盖 foo() 也会改变 bar() 的行为。 Child 的 "super" 打破了这一点。

根据经验,如果您在 "x()" 的实际 覆盖 之外的任何地方看到 "super.x()" 调用,则可能是潜伏在发生了。

如果你不压倒一切,我们来谈谈性能。

如果您在 class 中调用继承方法,比方说 methodInSuperclass(),JVM 将首先在您的 class 中查找该方法,然后在 class 层次结构,直到找到为止。

使用 super.methodInSuperclass() 告诉 JVM 直接转到 superclass 寻找那个方法。

因此,使用 super 关键字可将性能提高几倍。这是一段丑陋的代码,但它并不是多余的,因为它会带来一些性能提升。

如果时间紧迫,可以考虑使用它。