Java类继承编译器如何知道需要使用哪个方法

0 java methods inheritance class

有人可以解释编译器如何计算出他应该采用哪种方法

class All { /* ... */ }
class Most extends All { /* ... */ }
class Special extends Most { /* ... */ }

class Top {
    public void m( All p ) { System.out.print("A "); }
}

class Middle extends Top {
    public void m( All p ) { System.out.print("M "); }
    public void m( Special p ) { System.out.print("L "); }
}

class Bottom extends Middle {
    public void m( Most p ) { System.out.print("V "); }
    public void m( Special p ) { System.out.print("X "); }
}

class Test {
    public static void run() {

        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 );
        x.m( special );
        y.m( all );
        y.m( special );
        z.m( all );
        z.m( most );
    }
}
Run Code Online (Sandbox Code Playgroud)

例如,您会在这段代码中看到top, middleandbottomall, mostand的类继承。special如果我运行它,我会得到 的输出M M M M M M

我需要知道为什么编译器总是采用中类的方法m()。

为什么x.M(special)不打印出L?
为什么y.M(all)y.M(special)打印出M呢?

Jon*_*eet 6

这里涉及到两个方面:

  • 重载,发生在编译时,并根据编译时方法目标和参数选择适当的方法签名
  • Overriding,发生在执行时,并根据对象的执行时类型选择方法的实现(具有编译时选择的签名)。

在您的具体示例中,x.m(special)需要解析目标类型为Top编译时类型x)和参数Special(编译时类型special)的调用。

m在 中只调用了一种方法Top,那就是m(All),所以这就是编译器选择的方法(在验证存在从Special到 的隐式转换之后All)。x执行时,所引用的对象类型为 ,因此执行inMiddle的实现。同样, 的编译时类型是,因此选择了签名,并且实际上是 的实例并不重要,因为不会覆盖。m(All)MiddleyTopm(All)yBottomBottomm(All)