3

我有以下代码片段:

class BaseClass {
    public Integer getX() {
        return 5;
    }
}

class InheritedClass extends BaseClass implements Interface {
}

interface Interface {
    public Number getX();
}

public class Test5 {
    public static void main(String[] args) throws Exception {
        System.out.println(InheritedClass.class.getMethod("getX").getReturnType());
    }
}

这段代码返回java.lang.Number,这对我来说很奇怪,因为 BaseClass 的getX方法返回java.lang.Integer。最有趣的是,如果BaseClass实现了Interface,返回的类型是java.lang.Integer...这是正常的行为吗?

4

4 回答 4

2

这是我认为会发生的事情。

通过同时扩展BaseClass和实现Interface,子类承诺提供两种getX()方法:

public Integer getX();
public Number getX();

由于您不能重载返回类型,因此只能有一种方法。此外,它的返回类型必须是Number而不是Integer(因为您可以将后者转换为前者,反之则不行)。

为了协调上述所有内容,编译器会自动在 中生成以下方法InheritedClass

  public java.lang.Number getX();
    Code:
       0: aload_0       
       1: invokevirtual #22                 // Method getX:()Ljava/lang/Integer;
       4: areturn       

如您所见,它具有 in 方法的签名Interface,但会自动委托给 in 方法BaseClass(带有隐式向上转换)。

这种自动生成的方法是您的反射代码正在使用的方法。

于 2013-03-07T15:24:22.740 回答
1

是的,这很正常:

  • Integer是一个子类Number
  • 从 Java 5.0 开始,Java 中的派生类或接口实现方法可以返回父类或接口中声明的返回类型的子类。这称为返回类型协方差
  • 因为InheritedClass实现了Interface,所以使用来自该接口的返回类型getX,即Number.
于 2013-03-07T15:16:59.607 回答
0

JLS 的相关部分是§8.4.8.4

一个类可以继承多个具有重写等效签名的方法(第 8.4.2 节)。

如果其中一个继承的方法不是abstract......则abstract认为不是的方法会覆盖并因此实现代表继承它的类的所有其他方法。

我们在这里考虑的两种方法是:

  • public Integer getX();
  • public abstract Number getX();

由于BaseClass.getXis not abstract,并且它是可返回类型可替换的Integer是 的子类NumberInterface.getXBaseClass.getX因此选择覆盖Interface.getX

这很奇怪,因为这不是您看到的结果。但是,如果你尝试在 中定义一个方法public Number getX()InheritedClass你会收到一个错误,这与上面的一致。

于 2013-03-07T15:44:15.573 回答
-1

这是包含泛型的 Java 框架 1.6 的功能。Integer 和 Double 是 Number 的子类型。

于 2013-03-07T15:27:25.180 回答