【问题标题】:Method overloading/overriding in Java subclass object with superclass reference variable具有超类引用变量的 Java 子类对象中的方法重载/覆盖
【发布时间】:2012-09-25 16:50:33
【问题描述】:
 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'。有人可以解释一下这段代码是如何工作的吗?

【问题讨论】:

    标签: java class inheritance


    【解决方案1】:

    (通过对参数类型和实现使用相同的继承层次结构,您使这变得比需要的更混乱。将它们分开可能有助于在您的脑海中简化它。)

    c1 的类型是A。因此,在确定要调用哪个方法签名时,编译器只能查看A中声明的方法。

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

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

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

    请记住:

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

    【讨论】:

    • 第一种情况,c1是C的一个实例,所有的m1都是实例方法,那为什么在创建C的实例的时候编译器会调用A的方法呢?
    • @user39929:当编译器看到c1.m1时,它只关心c1compile-time类型,即A
    • @JonSkeet 您是否只花了 4 分钟就给出了简洁的答案?太棒了。
    • @CodeEnthusiastic:我可能在原始答案后的 5 分钟内对其进行了编辑。但这并不复杂:)
    猜你喜欢
    • 2023-04-11
    • 2015-11-30
    • 1970-01-01
    • 2011-11-14
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多