2012-03-29 152 views
3

泛型參數說我有一個父接口/類像這樣充分利用超類

interface Parent<T> {} 

和一批實施該解決通用型接口。

interface Child extends Parent<Type> {} 

我可以使用反射,如果我有Class對象Child獲得的代表TClass實例。事情是這樣的:

<T, I extends Parent<T>> I create(Class<I> type) { 
    Class<T> tType = ... 
    ... 
} 

目前我有tType作爲參數傳入,但我想,如果我可以把事情簡單化。

回答

6

是的,儘管別人都說過,但如果您有權訪問子類「Class」對象,則此信息。您需要使用getGenericSuperclass以及getActualTypeArguments

ParameterizedType superClass = (ParameterizedType)childClass.getGenericSuperclass(); 
System.out.println(superClass.getActualTypeArguments()[0]); 

在你的榜樣,「實際」的類型參數應該Type返回Class

+0

這適用於直接父類型,但不適用於任何祖先類型。如果有內置方法,對於任何'T對象'和'Class ancestorType',這將是很好的,以獲得'ancestorType'的'object'類型參數。 – 2014-11-20 01:28:18

+1

@丹尼爾,是的,但使用一點回憶,你應該能夠從任何特定的基類中派生你想要的任何類型的參數。您應該能夠創建一個方法,允許您指定未被通用的泛型'Class'和類型參數的索引(對於該泛型類),並從任何子類獲取該類型參數的'Class'。 – 2014-11-20 01:32:16

-3

我不這麼認爲。閱讀關於type erasure:泛型類型僅用於編譯時檢查,然後丟棄。它們不存儲在已編譯的類文件中,因此它們在運行時不可用。

+0

我希望爲他們固定在子類的聲明,這將是訪問。 – sblundy 2012-03-29 23:08:58

+0

不是。在運行時,它實際上就是'interface Child extends Parent'。我認爲編譯類中保留的唯一泛型信息是類型參數的名稱 - 例如,您可以通過在「Parent」接口上反射來獲取字符串「T」。 – Wyzard 2012-03-29 23:13:11

+1

這個答案是錯誤的。信息存儲在* class *文件中,它只是在方法的運行時處理中不可用。查看[相關的javadocs](http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/ParameterizedType.html)。 – 2012-03-29 23:31:09

0

如果您需要在運行時對泛型類型進行不平凡的操作,請考慮Guava的TypeToken。它可以回答你的問題,同時解決一些通過評議提出的細緻入微的關注(還有更多!):

private interface Parent<T> {} 
private interface Intermediate<U, V> extends Parent<V> {} 
private interface Child<Z> extends Comparable<Double>, Intermediate<Z, Iterable<String>> {} 

public void exploreGuavaTypeTokens() { 
    final TypeToken<? super Child> token = TypeToken.of(Child.class).getSupertype(Parent.class); 
    final TypeToken<?> resolved = token.resolveType(Parent.class.getTypeParameters()[0]); 
    System.out.println(resolved); // "java.lang.Iterable<java.lang.String>" 
    final Class<?> raw = resolved.getRawType(); 
    System.out.println(raw); // "interface java.lang.Iterable" 
}