2017-03-02 155 views
2

我有這樣一類獲取泛型類

public class RequestDataEditor<T> extends PropertyEditorSupport { 
    @Override 
    public void setAsText(String text) { 

     MyData<T> value; 

     try { 
      //(ParameterizedType)getClass().getGenericSuperclass() 

      value = JacksonUtil.parse(text, new TypeReference<MyData<T>>() { 
      }); 
     } catch (Exception e) { 
      value = null; 
     } 

     setValue(value); 
    } 
} 

當我運行(ParameterizedType)getClass().getGenericSuperclass(), 想到被T,但它的PropertyEditorSupport,不能被鑄造到ParameterizedType;

如果我刪除extends PropertyEditorSupport,然後我就可以得到通用的類型。(證明是錯誤的,我在這裏犯了一個錯誤。)

看來,我們不能用(ParameterizedType)getClass().getGenericSuperclass()來獲得普通型父類沒有泛型類的類。

那麼我怎樣才能得到像RequestDataEditor這樣的類的泛型?

not duplicate with the question,我想知道當使用(ParameterizedType)getClass().getGenericSuperclass()時有什麼不同,一個類有一個沒有泛型類的超類。

+0

泛型是編譯時安全檢查。它們在運行時不包含任何可用的類型信息。 – 4castle

+0

@ 4castle但是,如果'RequestDataEditor'類沒有父類,那麼我們可以得到泛型類型 – JackYe

+0

如果刪除'extends PropertyEditorSupport','getGenericSuperclass()'只返回'class Object'。請提供[mcve]進行測試。 – kennytm

回答

2

當我運行(ParameterizedType)的getClass()getGenericSuperclass(), 想到被T,但它的PropertyEditorSupport,並且不能被強制轉換爲 ParameterizedType;

如果您想要訪問T(即類型參數),則適當的反射方法是Class.getTypeParameters

// Test.java: 
class Generic<T> { 
} 

class Main { 

    public static void main(String[] args) { 

    final Generic<Integer> gint1 = new Generic<Integer>(); 

    System.err.println("gint1's type-parameter: " 
         + gint1.getClass().getTypeParameters()[0]); 
    } 
} 

如果你運行你上面得到下面的代碼:

$ javac Test.java 
$ java Main 
gint1's type-parameter: T 

注意,類型參數未解析爲整數,但作爲T因爲這種信息無法在運行時。

如果訪問這些信息對您很重要,那麼您有兩個簡單的選項。

A.對象包含實際類型的類的引用:

class Generic<T> { 

    public final Class<T> type; 

    public Generic(Class<T> type) { 
     this.type = type; 
    } 

    public Class<T> type() { 
     return type; 
    } 
} 

class Main { 
    public static void main(String[] args) { 

     final Generic<Integer> gint2 = new Generic<>(Integer.class); 
     System.err.println("gint2's type-parameter: " + gint2.type().getSimpleName()); 
    } 
} 
// Output will be "gint2's type-parameter: Integer". 

B.你創建一個子類,給出了一個具體的類爲該類型的參數:

import java.lang.reflect.*; 

class Generic<T> { 
} 

class IntegerGeneric extends Generic<Integer> { 
} 

class Main { 
    public static void main(String[] args) { 

     final Generic<Integer> gint3 = new IntegerGeneric(); 
     final Generic<Double> gint4 = new Generic<Double>() {}; 
     System.err.println("gint3's type-parameter: " 
      + ((ParameterizedType)gint3.getClass().getGenericSuperclass()).getActualTypeArguments()[0]); 
     System.err.println("gint4's type-parameter: " 
      + ((ParameterizedType)gint4.getClass().getGenericSuperclass()).getActualTypeArguments()[0]); 
    } 
} 
// Output: 
// gint3's type-parameter: class java.lang.Integer 
// gint4's type-parameter: class java.lang.Double 

注意gint4類不是Generic<Double>,而是由匿名內部類擴展它,由於構造函數後面的{} ...這是完整的class DoubleGeneric ...聲明的替代方法。

在這兩個替代方案中,A.和B.,A.因爲通常應該避免依賴反思;除此之外,它更容易隱藏運行時錯誤,代碼更難以維護。

我想知道有什麼不同,當使用 (ParameterizedType)的getClass()。getGenericSuperclass()一類具有 一個沒有泛型類型的超類。

如果您查找的Type文檔,類此方法返回的引用,它表示這是一個「保護傘」超級接口爲所有對象/數據類型可以在Java語言中甚至包括primitives ...所以對於沒有泛型超類的類我想它會返回一個反映該類型的子類...

一個快速實驗顯示,實際上它會返回一個'Class'對象它相當於getSuperclass()。

也許其他人可以對此有更多的瞭解,但我認爲這可能有點誤會......我認爲getSuperType()或類似的東西會更合適。也許最初它只支持較舊的Java版本(1.5版本)中的泛型,並最終擴展到涵蓋其他數據類型,但這是我的一個猜測,而沒有考慮它的歷史。

+0

感謝您的詳細解釋! – JackYe

2

(ParameterizedType)getClass()。getGenericSuperclass()將獲得當前類的超類,該類不是通用類。你想要的是當前類的泛型類型,而不是它的超類。在你的例子中,這是不可能的,因爲這些數據在運行時不再可用。一個可能的解決方案是:

public class RequestDataEditor<T> extends PropertyEditorSupport { 

    private final Class<T> genericType; 

    public RequestDataEditor(Class<T> genericType) { 
     this.genericType = genericType; 
    } 

    @Override 
    public void setAsText(String text, ) { 

     MyData<T> value; 

     try { 
      //use genericType here 

      value = JacksonUtil.parse(text, new TypeReference<MyData<T>>() { 
      }); 
     } catch (Exception e) { 
      value = null; 
     } 

     setValue(value); 
    } 
} 

我知道這是不是正是你試圖達到的目標,但它是你可以得到的最接近(據我所知)。 。

+0

Thx。我犯了一個錯誤。你的回答幫助我更深入地理解getGenericSuperclass()方法。 – JackYe

+0

不客氣。你解決了你的問題嗎? – mahieus