2012-06-08 50 views
3

考慮下面的Java代碼:使用Java Reflections來查找Collection的元素類型?

public class Test 
{ 
    private Foo< String, String > foo1; 
    private Foo< Integer, Integer > foo2; 
} 

public class Foo< T, V > 
{ 
    private Bar<V> bar; 
    private T a; 
} 

public class Bar<T> 
{ 
    @MyAnnotation 
    private List<T> list; 
} 

首先,在開始與名爲「測試」,我遞歸搜索所有領域的類,它被標註了「MyAnnotation」和它的類型是從公司的Java的。 lang.Collection」。對於給定的例子,結果將是:

  • Test.foo1.bar.list
  • Test.foo2.bar.list

這是obviosly明確的,即第一個只能拿字符串的元素,而第二個只能採取整數。

我的問題是:什麼是最好的(最簡單的)的方式來找到「MyAnnotation」和註釋所有收藏領域的告訴自己的元素類型

找到類型爲java.lang.Collection的註釋字段不是問題。但是對於給定的例子,我們怎麼能得到如下的結果呢?

  • Test.foo1.bar.list <字符串>
  • Test.foo2.bar.list <整數>

我試過幾種方法,它總是給我的 '對象' 爲集合的元素類型而不是「String」。

我真的堅持這一點。 非常感謝提前!

+0

您是否試過[this](http://stackoverflow.com/a/1942680/1321716)? –

+0

相關:http://stackoverflow.com/questions/3450505/java-generics-reflection-generic-field-type-of-subclass – assylias

+0

@MattiasBuelens您鏈接的主題處理不同類型的問題。 – theV0ID

回答

1

這是不可能的,因爲Java的類型擦除。編譯時,泛型類型將原始類型來代替,造成這樣的:那麼

public class Test 
{ 
    private Foo foo1; 
    private Foo foo2; 
} 

public class Foo 
{ 
    private Bar bar; 
    private Object a; 
} 

public class Bar 
{ 
    @MyAnnotation 
    private List list; 
} 

的實際類型填入你在哪裏直接與foo1foo2工作場所。例如,下面的代碼:

Test test = new Test(); 
List<String> a = test.foo1.bar; 
String b = a.get(0); 
Integer b = test.foo2.a; 

將被轉換爲類似:

Test test = new Test(); 
// The generic type is erased here... 
List a = test.foo1.bar; 
// ...and a cast is added here 
String b = (String) a.get(0); 
Integer b = (Integer) test.foo2.a; 

長話短說:有沒有辦法可以檢索類型,因爲它是在編譯時丟棄。

+0

@statoverflow.com/questions/2320658/why-are-not-all-type-in​​formation-erased-in-java-at-runtime –

+0

@MatthiasWuttke不知道你在嘗試什麼在這裏說,你沒有真正評論很多。這個問題是關於獲取泛型類型信息的「技巧」,但它依賴* always *使用(匿名)超類來填充泛型,並且在所有情況下都不起作用(例如'new ArrayList () {};'不起作用)。儘管如此,我還是沒有看到這與*這個問題有什麼關係...... –

+0

我發現了兩個使用谷歌的問題,第二個鏈接幫助我解決了我的問題。 (我需要找到一個集合字段的泛型類型參數。)雖然你的答案當然是正確的,並有助於理解Java類型的刪除,但我鏈接的問題解決了我的問題。我添加了評論來幫助他人,但應該添加更多的鏈接。我不想踩你的腳,所以請接受我的道歉。 –

7

可能是你可以嘗試這樣的:

Field field = Test1.class.getField("list"); 

Type genericFieldType = field.getGenericType(); 

if(genericFieldType instanceof ParameterizedType){ 
    ParameterizedType aType = (ParameterizedType) genericFieldType; 
    Type[] fieldArgTypes = aType.getActualTypeArguments(); 
    for(Type fieldArgType : fieldArgTypes){ 
     Class fieldArgClass = (Class) fieldArgType; 
     System.out.println("fieldArgClass = " + fieldArgClass); 
    } 
} 

這將返回fieldArgClass = java.lang.String

+0

您的班級'Test1',是我的班'Test'還是'Bar'? – theV0ID

+0

你的Test.Bar.foo與這裏有關嗎?或者你可以詳細說明一下 – UVM