簡體   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