使用继承的重载方法

2022-09-02 00:28:35

我有两个类:

public class ClassA {
    public void method(Number n) {
        System.out.println("ClassA: " + n + " " + n.getClass());
    }
}

和:

public class ClassB extends ClassA {            
    public void method(Integer d) {
        System.out.println("ClassB: " + d + " " + d.getClass());
    }
}

但是当我跑步时:

ClassA a = new ClassB(); 
a.method(3);

我得到:

ClassA: 3 class java.lang.Integer

我的问题是,为什么不使用 的方法? 是 的一个实例,并且 's 有一个参数...ClassBaClassBClassBmethod()Integer


答案 1

我的问题是,为什么不使用ClassB的方法?

事实并非如此。使用的方法就是 的方法,它继承自 。ClassBClassA


我认为这里混淆的主要原因是,该方法实际上没有被覆盖,而是被重载。虽然 是 的子类型,但由于方法参数在 Java 中是不变的,因此该方法不会覆盖该方法。因此,最终有两个(重载的)方法。IntegerNumberpublic void method(Integer d)public void method(Number n)ClassB

静态绑定用于重载方法,具有最具体参数类型的方法由编译器选择。但是在这种情况下,为什么编译器选择而不是 .这是因为您用于调用该方法的引用类型为 。public void method(Number n)public void method(Integer d)ClassA

ClassA a = new ClassB(); //instance is of ClassB (runtime info)
a.method(3);             //but the reference of type ClassA (compiletime info)

唯一的方法是 ,所以这就是编译器拾取的内容。请记住,此处的预期参数类型是 ,但传递的实际参数(整数 3)将自动装箱到类型 。它之所以有效,是因为方法参数在Java中是协变的ClassApublic void method(Number n)NumberInteger

现在,我认为很明显为什么它打印

ClassA: 3 class java.lang.Integer


答案 2

您的问题源于以下事实(引用自有关继承的官方 Java 教程):

在子类中,可以重载从超类继承的方法。这种重载方法既不隐藏也不覆盖超类方法——它们是子类独有的新方法。

有关更多详细信息,请参阅官方 Java 教程:http://docs.oracle.com/javase/tutorial/java/IandI/override.html