繁体   English   中英

当子类覆盖它们时,为什么我通过反射获取基类方法?

[英]Why do I get the base class methods via reflection when the subclass overrides them?

我有超级班:

class MyClass<T> {
  public void setValue(T value){
    //insert code
  }

  public T getValue(){
    return null;
  }
}

然后我有一个具体的推导

class MyClassImp extends MyClass<String> {
  @Override
  public void setValue(String value){
    //insert code
  }

  @Override
  public String getValue(){
    return null;
  }
}

关于MyClassImpl反思:

Class clazz = MyClassImpl.class;
Method[] methods = clazz.getDeclaredMethods();

我得到了超类实现java.lang.Object getValue()void setValue(java.lang.Object)java.lang.String getValue()void setValue(java.lang.String)

根据Class.getDeclaredMethods() vis-a- Class.getDeclaredMethods()的Java文档

返回一个Method对象数组,这些对象反映由此Class对象表示的类或接口声明的所有方法。 这包括公共,受保护,默认(包)访问和私有方法,但不包括继承的方法。 返回的数组中的元素没有排序,也没有任何特定的顺序。 如果类或接口未声明任何方法,或者此Class对象表示基本类型,数组类或void,则此方法返回长度为0的数组。 类初始化方法<clinit>不包含在返回的数组中。 如果类声明具有相同参数类型的多个公共成员方法,则它们都包含在返回的数组中。

为什么我得到超类型实现? 有什么我想念的吗?

我需要这个的原因是我在基类实现上反射性地调用setValue ,我已经添加了一些特殊的注释注释,当然还有其他约束。

这是因为编译的类实际上申报setValue(Object) 该方法将转换为String,然后调用强类型方法。 同样, getValue(Object)调用getValue(String)

基本上这是必需的,因为JVM并不真正了解泛型(至少不是深入的) - 为了在JVM级别覆盖超类方法,它必须具有相同的签名。

javap -c MyclassImp看一下这个类,你会看到额外的合成方法:

public java.lang.Object getValue();
  Code:
   0:   aload_0
   1:   invokevirtual   #3; //Method getValue:()Ljava/lang/String;
   4:   areturn

public void setValue(java.lang.Object);
  Code:
   0:   aload_0
   1:   aload_1
   2:   checkcast       #4; //class java/lang/String
   5:   invokevirtual   #5; //Method setValue:(Ljava/lang/String;)V
   8:   return

}

正如Jon先前所说, 类型信息在运行时会丢失

因此,无论何时使用泛型,编译器都会将所有这些“通用”继承方法放在子类中。 非通用代码也是如此。

我刚检查过:当我从超类中删除了通用相关代码( <T>部分)时,反射代码在子类中给了我两个方法,即使它覆盖了它们。 这意味着文档应该对通用相关代码有点明确。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM