Java多态性练习

时间:2018-08-02 00:12:36

标签: java compiler-construction polymorphism runtime late-binding

有人可以解释一下编译器/运行时如何运行 示例中的适当方法? 有6个类和带有不同参数的方法void m(/* ... */)。 我知道编译器会分析 声明的类型。 输出始终是中产阶级的“ M”。

public class All {}
public class Most extends All {}
public class Special extends Most {}

public class Top {
    public void m( All p )     { System.out.println("A"); }
}
public class Middle extends Top {
    public void m( All p )     { System.out.println("M"); }
    public void m( Special p ) { System.out.println("L"); }
}
public class Bottom extends Middle {
    public void m( Most p ) { System.out.println("V"); }
    public void m( Special p ) { System.out.println("X"); }
}

public class Main {

  public static void main(String[] args) {
    All all = new All();
    Most most = new Most();
    Special special = new Special();

    Top x = new Middle();
    Top y = new Bottom();
    Middle z = new Bottom();

    x.m( most );     // Output is M
    x.m( special );  // Output is M
    y.m( all );      // Output is M
    y.m( special );  // Output is M
    z.m( all );      // Output is M
    z.m( most );     // Output is M
  }
}

1 个答案:

答案 0 :(得分:4)

方法覆盖在运行时通过查看对象的运行时类型来解决。编译器还可以决定要调用的方法,但是只能根据表达式的编译时类型来决定。

对于x上的两次调用,它们都在编译时解析为Top.m(All)x的编译时类型为Top,因此编译器只能查找在Top及其超类中声明的方法。编译器发现唯一可用的方法是m(All)。在运行时,要调用的方法解析为Middle.m(All)。这是因为x的运行时类型实际上是Middle,因此运行时将在m(All)中调用覆盖的Middle。为什么不叫Middle.m(Special)?编译器已经决定应调用Top.m(All)。运行时仅检查运行时类型是否已覆盖该类型。编译器不知道存在Middle.m(Special),因为x的编译时类型为Top

y上的两个呼叫是相似的。 y的编译时间类型仍为Top,因此编译器将方法解析为Top.m(All)y的运行时类型为Bottom。由于Bottom继承自Middle,因此它也会覆盖Top.m(All)。实现与Middle中的实现相同。因此,被覆盖的方法在运行时被调用。

z上的两个调用有些不同,但是它们最终仍会解析为Middle.m(All)z的编译时间类型为Middle,因此两个调用都解析为Middle.m(All)。请注意,没有Middle.m(Most),因此呼叫z.m(most)仍将解析为Middle.m(All)。在运行时,由于运行时类型Middle.m(All)不会覆盖Bottom,因此该方法仍解析为Middle.m(All)