Skip to content

Java 的多态和方法重载

先看一段代码,他会输出什么:

java
class A {
    public void f(){
        System.out.println("A.f()");
    }
}

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

class C{
    public void g(A a){
        System.out.print("g(A a) ");
        a.f();
    }

    public void g(B b){
        System.out.print("g(B b) ");
        b.f();
    }
}

public class Main {
    public static void main(String[] args) {
        C c = new C();
        A e = new B();
        c.g(e);
    }
}

A. g(A a) A.f() B. g(A a) B.f() C. g(B b) A.f() D. g(B b) B.f()

答案是B,输出了g(A a) B.f()

这是Java的多态性和方法重载的特性在起作用。

首先,创建了一个B类的对象,并将其引用类型设为A类(A e = new B();)。这是Java的多态性的一个例子,即子类对象可以当作父类对象来处理。

然后,调用了C类的g方法(c.g(e);)。根据Java的方法重载规则,编译器会在编译时期根据参数的静态类型(也就是引用类型)来决定调用哪个版本的g方法。因为你的e变量的引用类型是A类,所以编译器选择了g(A a)这个版本的方法。

g(A a)方法中,又调用了a.f()。这时,Java的动态绑定(也称为后期绑定或运行时绑定)机制起作用了。动态绑定意味着在运行时期,根据对象的实际类型(也就是new操作符后面的类型)来决定调用哪个版本的方法。因为你的e变量实际指向的是一个B类的对象,所以这里调用了B类的f方法,输出了B.f()

所以,整个过程中,g(A a)是由于方法重载在编译时期的静态绑定结果,而B.f()是由于多态性在运行时期的动态绑定结果。