如果我有2个类,其中一个是具有以下内容的父类:
public class Parent {
...
public void method1() {
method2();
}
public void method2() {
}
}
然后在子类中
public class Child extends Parent {
...
public void method2() {
...
}
}
如果我运行以下代码:
Child c = new Child();
c.method1();
调用哪个版本的method2?
答案 0 :(得分:5)
Java中的所有方法都是virtual,这意味着它将被调用Child.method2
(即使调用是从Parent
的上下文完成的)。
如果Parent.method1
的正确性依赖于method2
的实施,则应该采用不同的方式进行设计:
public class Parent {
...
public void method1() {
method2impl();
}
public void method2() {
method2impl();
}
// make it private or final.
public final method2impl() {
...
}
}
答案 1 :(得分:3)
Child#method2
,因为它会覆盖父级的。{/ p>
答案 2 :(得分:3)
一旦创建了Child
类型的对象,那就是它的运行时类型。这不会改变,无论演员阵容或你做什么。调用方法时,将执行该运行时类型的实现。如果该类型没有自己的实现,它将委托给父类。
即使你调用method1
中定义的Parent
,一旦该方法调用method2
,它将解析为对象的运行时类型的实现。如果那是Child
,那就是将要调用的类'方法。
请注意,此动态行为与选择基于参数类型的方法不同,这是静态完成的。请按照以下类别定义......
public void methodTest(Parent p) {} //Let's call this "first method"
public void methodTest(Child c) {} //Let's call this "second method"
Parent p = new Parent();
Child c = new Child();
//Assume a is a variable of some type that implements the above methods
a.methodTest(p); //Will call first method
a.methodTest(c); //Will call second method
a.methodTest((Parent)c); //WILL CALL FIRST METHOD!
因此,静态地选择基于参数类型的方法。它不会根据运行时类型选择不同的方法。
但是根据调用它的对象选择一个方法取决于该对象的运行时类型。这就是允许我们覆盖子类中方法行为的原因。
答案 3 :(得分:0)
public class Parent {
public void method1() {
method2();
}
public void method2() {
System.out.println("parent m 2");
}
}
public class Child extends Parent {
public void method2(){
System.out.println("child m 2");
}
}
public class Main {
public static void main(String[] args) {
Child c = new Child();
c.method1();
System.out.println("________________");
c.method2();
}
}
输出将是:
child m 2
________________
child m 2
答案 4 :(得分:0)
我还有一些问题要问你:
public interface CanDoMethod1 {
public void method1();
}
public class Parent implements CanDoMethod1 {
public void method1() {
System.err.println("Parent doing method1");
}
}
public class Child extends Parent {
public void method1() {
System.err.println("Child doing method1");
}
}
现在运行以下代码:
CanDoMethod1 instance = new Parent();
instance.method1();
输出是什么?
当你跑步时:
CanDoMethod1 instance = new Child();
instance.method1();
那么输出是什么?
当你跑步时:
Parent instance = new Child();
instance.method1();
那么输出是什么? 为什么这里不需要演员?
当你跑步时:
Child instance = (Child) new Parent();
instance.method1();
这会编译吗? 如果是这样,那么输出是什么?
总之,请注意所调用的方法始终是您创建的实现类的方法,无论您将其投射或分配给它。