使用超类引用变量在Java子类对象中重载/覆盖方法

时间:2012-09-25 16:50:33

标签: java class inheritance

 class A{
 void m1(A a) {System.out.print("A");}
  } 
  class B extends A{
  void m1(B b) {System.out.print("B");}
  } 
  class C extends B{
  void m1(C c) {System.out.print("C");}
  }

 public class d {

 public static void main(String[] args) {

  A c1 = new C(); C c2 = new C();c1.m1(c2);

 }}

此代码的输出为'A'

但如果我将A类修改为:

 class A{
 void m1(C a) {System.out.print("A");}
  }

然后输出为'C'。有人可以解释这段代码是如何工作的吗?

1 个答案:

答案 0 :(得分:10)

(通过对参数类型和实现使用相同的继承层次结构,你已经使它变得更加混乱。分离它们可能有助于在你的脑海中简化它。)

c1的类型为A。因此,在计算出要调用的方法签名时,编译器只能查看A中声明的方法。

所以在第一种情况下,编译器将调用m1(A);在第二种情况下,编译器将调用m1(C)

现在在第一种情况下,m1(A)方法永远不会被覆盖,因此c1的执行时类型实际上是无关紧要的。

在第二种情况下,m1(C)会覆盖C,因此调用C中的实现,因为c1的执行时类型为C }。

请记住:

  • 重载解析(调用哪个方法签名)在编译时根据方法目标和参数表达式的编译时类型确定
  • 该方法签名(重写)的实现基于执行时的目标对象的实际类型。