2010-02-16 57 views
5

有關Java中的類型擦除處理的大多數文檔假定用例處理的類型如SomeType<ParamType>。 我試圖處理方法參數如下方法:Java:在嵌套參數化類型中獲取內部類型(反射)

public void setOtherReferenceRanges(List<ReferenceRange<T>> referenceRanges) 

當容器類與一類DvQuantity實例化,這個簽名應該成爲在運行時 public void setOtherReferenceRanges(List<ReferenceRange<DvQuanitity>> referenceRanges)

使用反射可以看到List有一個actualTypeArgument這是ReferenceRange<T>。由於反射使用類信息,我不希望它給我ReferenceRange<DvQuantity>。 但是,當我創建包含此方法的類時,我通過了DvQuantity類型T。所以填充T的類型應該可用於Java運行時,但我找不到獲取它的方法。我最終通過反射訪問了一個TypeVariableImpl對象,該對象似乎沒有包含任何有用的數據。

你能想出任何方法來發現運行時的這些信息嗎?

回答

1

當你說

,當我創建了一個包含這個方法

我猜你的意思是,當你創建一個類型的對象,例如類:

foo = new ContainerClass<DvQuantity>(); 

在這種情況下,由於擦除,無法恢復類型DvQuantity

但是,如果你創建一個傳遞一個類型參數的超類,這樣

class DvQuantityContainerClass extends ContainerClass<DvQuantity> {...} 
... 
foo = new DvQuantityContainerClass(); 

或者更短,內聯匿名子類(這看起來幾乎像第一個例子,但有一個微妙但重要的區別):

foo = new ContainerClass<DvQuantity>(){}; 

然後你就可以恢復的數據類型參數,因爲你恢復用來在運行時擴展超類型參數。不幸的是,Java本身並沒有提供一種簡單的方法,現在讓DvQuantityContainerClass.setOtherReferenceRanges法填補了T的類型對於這一點,我已經寫gentyref,做先進的反射泛型類型:

Method m = DvQuantityContainerClass.class.getMethod("setOtherReferenceRanges", List.class); 
// this will return List<ReferenceRange<DvQuanity>>, like you are lookingn for 
return GenericTypeReflector.getExactParameterTypes(m, DvQuantityContainerClass.class) 
+0

感謝您的回覆。它驗證了迄今爲止我所看到的。不幸的是,我沒有權力在我需要做這項工作的設置上。還要感謝其他答覆,如果我能夠控制這種情況,所有這些答案都會有用。 – mahonya 2010-02-16 14:36:58

0

通用類型信息是erased by the compiler並且在運行時不可用。當我需要確保在運行某些類型的我通過在一個類的說法:

public <T> void doSomething(T t, Class<T> c); 

這並不總是很方便,甚至是不可能的,但許多情況下,它是可能的。

0

因此,填充T的類型應該可用於Java運行時,但我找不到獲取它的方法。

也許它不完全正確,但我認爲它的方式是在運行時沒有實際的類 - 只是沒有滿足T的接口的特定類型的對象。換句話說,擦除不會發生與對象,而是與這些模糊的(至少在OOP世界)類型的東西。

http://java.sun.com/docs/books/tutorial/java/generics/erasure.html

有捕獲類本身內部的類型信息(T類型需要一個方法getUnderlyingType()...或東西)的方式,但是這是一個壞主意。如果你真的需要原始類型的對象,我會重新考慮使用泛型。