Java重载和继承规则

Posted

技术标签:

【中文标题】Java重载和继承规则【英文标题】:Java overloading and inheritance rules 【发布时间】:2012-06-22 01:30:26 【问题描述】:

我一直在学习,因为我要参加考试,而且我对 Java 的大部分内容都没有太多问题,但我偶然发现了一条我无法解释的规则。这是一个代码片段:

public class A 

    public int method(Object o) 
        return 1;
    

    public int method(A a) 
        return 2;
    


public class AX extends A 

    public int method(A a) 
        return 3;
    

    public int method(AX ax) 
        return 4;
    


public static void main(String[] args) 
    Object o = new A();
    A a1 = new A();
    A a2 = new AX();
    AX ax = new AX();

    System.out.println(a1.method(o));
    System.out.println(a2.method(a1));
    System.out.println(a2.method(o));
    System.out.println(a2.method(ax));

这会返回:

1 3 1 3

虽然我希望它会返回:

1 3 1 4

为什么是a2的类型决定了AX中调用哪个方法?

我一直在阅读有关重载规则和继承的内容,但这似乎很模糊,以至于我无法找到确切的规则。任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

这些方法调用的行为由 Java Language Specification 规定和描述(参考第 8.4.9 节)。

当调用方法时(第 15.12 节),实际参数的数量(以及 任何显式类型参数)和 在编译时使用参数来确定 将被调用的方法(§15.12.2)。如果要采用的方法 invoked 是一个实例方法,要调用的实际方法将是 在运行时确定,使用动态方法查找 (§15.12.4)。

在您的示例中,Java 编译器确定您调用方法的实例的编译类型最接近的匹配。在这种情况下:

A.method(AX)

最接近的方法来自类型 A,签名为 A.method(A)。在运行时,动态调度是在 A 的 actual 类型(它是 AX 的一个实例)上执行的,因此这是实际调用的方法:

AX.method(A)

【讨论】:

谢谢,我想我明白了。因此,本质上,Java 编译器在编译时确定要调用的方法的签名,而 JVM 像往常一样将调用分派给该签名的最具体的方法。对吗? @Lugaid - 就是这样。您示例中的棘手部分是超类没有为您调用其方法的参数提供精确匹配。【参考方案2】:

我会以更简单的方式澄清它。看看你何时使用超类引用创建子类对象,就像这里一样。

始终记住一件事,当您使用超类引用调用时,无论对象是否属于子类,它都会转到超类,检查具有此名称的方法以及正确的签名是否存在。

现在如果它会找到它,它会检查它是否被覆盖?如果是的话,它将像这里那样转到子类方法。另一个明智的做法是执行相同的超类方法。

我可以给你举个例子……只是隐藏

public int method(A a) 
        return 3;
    

方法和检查你的答案你会得到 1 2 1 2,为什么因为它优先考虑参考。因为你覆盖了它而不是调用它,所以它给了 3..!!希望它很大但很容易理解。快乐学习

【讨论】:

【参考方案3】:

a2 被引用为 A 并且 JVM 首先使用引用(而不是您期望的实际对象)。

【讨论】:

以上是关于Java重载和继承规则的主要内容,如果未能解决你的问题,请参考以下文章

关于Java中的继承,包括重写构造器访问权限构造过程等知识总结

Java中的(构造方法方法重载final修饰符使用及继承和抽象)

Java 继承与重写重载

Java面试题|方法重载和重写是什么?有什么区别?

JavaSE入门学习15:Java面向对象之J重写(Override)和重载(Overload)

Java重写重载与覆盖