Java中的方法覆盖和重载

Rez*_*eza 5 java methods overriding overloading

当我遇到一些奇怪的东西时,我正在测试代码,我无法弄清楚为什么会发生这种情况.所以我将举一个关于那里发生的事情的简单例子.

考虑这些课程

public class A {
    public void print(A a) {
        System.out.println("A");
    }
}

public class B extends A {
    public void print() {
        System.out.println("B");
    }
}

public class C extends B {
    public void print(A a) {
        System.out.println("C");
    }
}

public class E extends C {
    public void print(E e) {
        System.out.println("E");
    }
}
Run Code Online (Sandbox Code Playgroud)

现在在我的main方法中我有这种实例化:

    B b = new E();
    C c = new E();
    E e = new E();
Run Code Online (Sandbox Code Playgroud)

我调用这些方法并获得以下输出.

    b.print(b);
    c.print(e);
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

C
C
Run Code Online (Sandbox Code Playgroud)

我有两个解释,但每个解释都与这些方法调用之一相矛盾.也有可能我的两个解释都是完全错误的,所以我在这里没有任何要求.

解释1

  • b.print(b):b是的实例E,并upcasted到B.B有一个print方法,它接受类型的参数A但它被类重载E.但是,此方法的参数b是up upted B,因此方法调用匹配C.print(A a)(因为C是超类E)的签名,因此结果是合理的.

  • c.print(e):以同样的方式思考,不会在这里解释输出.c是一个实例E并且被提升为C.C有一个print方法,它接受类型的参数A但它被类重载E.但与上述情况相反,此方法的参数e与签名相匹配E.print(E e).所以通过这个推理,输出应该是E而不是!

解释2

在这里,我从第二个方法调用和原因开始.

  • c.print(e):c是的实例E,并upcasted到C.C有一个print接受类型参数的方法A.这个方法的参数e是一个实例,E而其实例又是它的子类A.因为它已被上传E.print(E e)隐藏起来c.因此,方法调用匹配签名,C.print(A a)并且该逻辑输出是合理的.

  • b.print(b):b是的实例E,并upcasted到B.B有一个print方法,接受类型的参数A(再次隐藏).因此,方法调用匹配签名,A.print(A a)并且通过该逻辑,输出应该是A,而不是.

我真的很困惑这里发生了什么.请有人解释一下.

Ada*_*ion 7

将调用哪种方法分两步:

  • 在编译时,根据声明的实例类型决定将使用哪个重载方法
  • 在运行时,根据实际实例类型(多态)确定将使用哪些重写方法

    1. b.print(b); // B b = new E();

      • 在编译时,由于声明的类型bB,只能使用print接受B(或其超类(A)的实例),这意味着:A.print(A a)

      • 在运行时,一旦重载方法已在先前步骤中选择,实际类型b(E)用于选择的版本print(A a)将用于:C.print(A a)A.print(A a)

    2. c.print(e); // C c = new E(); E e = new E();

      • 在编译时,声明的类型cC和声明的类型eE这样的,因此只能使用这些方法:A.print(A a)C.print(A a)

      • 因此,在运行时,实际的类型eE更具体的(在类层次结构中意味着更高)版本被选中:C.print(A a)