SJ1*_*J19 5 java methods overriding super
始终使用super来调用超类之外的方法是常见的做法,即使我没有覆盖该方法也是如此?
假设
public class Parent{
public void method() {
}
}
Run Code Online (Sandbox Code Playgroud)
所以
public class Child extends Parent {
public void someMethod() {
super.method();
}
}
Run Code Online (Sandbox Code Playgroud)
要么
public class Child extends Parent {
public void someMethod() {
method();
}
}
Run Code Online (Sandbox Code Playgroud)
感谢您的输入。
调用super告诉JVM 显式查找方法的父类版本。继续您的示例,如果您只是打电话
method()
Run Code Online (Sandbox Code Playgroud)
Child在查看父类之前,JVM将首先在调用类中搜索方法(在本例中为)。另一方面,如果您致电
super.method()
Run Code Online (Sandbox Code Playgroud)
那么JVM将显式查看父类的实现,即使该类Child具有名为的方法method()。
综合考虑这两个想法,super在打算调用父类的方法时,应该始终使用。如果您的类未覆盖该方法,则可以不使用进行调用super。但是,如果以后有人重构您的类并覆盖该方法,那么即使这样也会成为问题。
主要问题很容易回答:
即使我没有覆盖方法,也总是使用 super 来调用超类之外的方法是一种常见的做法吗?
不,这不是常见的做法。相反,这样做很危险。您通常调用方法,因为继承的主要目的是允许类覆盖方法以更改/扩展其行为。您通常不关心方法实际实现的级别。
明显的例外是当您自己重写方法并且您想要/需要父功能时。
现在到显式调用 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();
}
}
Run Code Online (Sandbox Code Playgroud)
如果您运行此示例,它将输出(为清楚起见添加了行号):
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
Run Code Online (Sandbox Code Playgroud)
前四行并不奇怪,我们得到了 foo 在每一层实现的东西,分别是父母的 bar 调用它的 foo。它在第 5 行开始变得奇怪。 Child 通过调用 super.bar() 绕过它自己的 foo 覆盖,因此虽然它的 foo() 是专门的,但 bar() 不是。在第 6 行中,您会看到 GrandChild 继承了 Child 的这个奇怪之处,因此 Child 的 bar 中看起来有些无辜的 super.foo() 现在打破了 GrandChild 的期望,即它对 foo() 的覆盖也对所有 bar() 有效。
现在,如果您想象 foo() 和 bar() 实际上做了一些有用的事情,并且它们彼此之间具有有意义的关系,例如,您会相信(通过父母的文档或只是常识)覆盖 foo() 将改变bar() 的行为也是如此。孩子的“超级”正在打破这一点。
根据经验,如果您在实际覆盖“x()”之外的任何地方看到“super.x()”调用,则可能是潜在的意外发生。