有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java中的反射与继承

我有以下代码片段:

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,这对我来说非常奇怪,因为基类的getX方法返回java.lang.Integer。最有趣的是,如果BaseClass实现了接口,则返回的类型是java。整型。。。这是正常的行为吗


共 (4) 个答案

  1. # 1 楼答案

    这是包含泛型的Java framework 1.6的一个函数。Integer和Double是数字的子类型

  2. # 2 楼答案

    是的,这是正常的:

    • IntegerNumber的一个子类
    • 从Java5.0开始,Java中的派生类或接口实现方法可以返回超类或接口中声明的返回类型的子类。这被称为return type covariance
    • 因为InheritedClass实现了Interface,所以使用了来自该接口的getX返回类型,即Number
  3. # 3 楼答案

    以下是我认为会发生的事情

    通过同时扩展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       
    

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

    这个自动生成的方法就是反射代码所采用的方法

  4. # 4 楼答案

    JLS的相关章节为§8.4.8.4

    It is possible for a class to inherit multiple methods with override-equivalent signatures (§8.4.2).

    If one of the inherited methods is not abstract... the method that is not abstract is considered to override, and therefore to implement, all the other methods on behalf of the class that inherits it.

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

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

    由于BaseClass.getX不是abstract,并且它是return-type-substitutableIntegerNumber的子类),因此Interface.getX选择BaseClass.getX来覆盖Interface.getX

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