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

Ris*_*abh 2 java inheritance class

 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);

 }}
Run Code Online (Sandbox Code Playgroud)

此代码的输出是'A'.

但是,如果我将A类修改为:

 class A{
 void m1(C a) {System.out.print("A");}
  }
Run Code Online (Sandbox Code Playgroud)

那么输出就是'C'.有人可以解释这段代码是如何工作的?

Jon*_*eet 10

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

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

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

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

在第二种情况下,m1(C)被覆盖C,因此执行in C是因为执行时类型c1C.

所以请记住:

  • 根据方法目标和参数表达式的编译时类型,在编译时确定重载分辨率(调用方法签名)
  • 该方法签名(覆盖)的实现基于执行时目标对象的实际类型.