2012-10-03 53 views
2

我知道如何使用反射來訪問泛型類型的字段:只需檢查field.getGenericType() instanceof ParameterizedType在運行時訪問對象的泛型類型

但是,如何檢查相同的任意對象,不知道它在哪裏宣佈?

+0

不輸入擦除類型排除了這種可能性嗎? – cdhowie

+0

問題是:'getGenericType()'是'Field'的一種方法,不能應用於任何'Object' ... –

回答

2

泛型適用於變量聲明,方法返回類型等,而不是對象本身。您可以通過myObj.getClass().getTypeParameters()確定特定對象的Class是否使用泛型,但無法確定使用哪種類型參數的值創建特定對象實例。

2

對象不存儲的通用信息本身,所以new ArrayList<Integer>()生成的字節碼是完全一樣的一個new ArrayList<String>()。我的意思是正好是。這就是Java泛型的類型擦除。他們只是傾向於new ArrayList()

但是,在幾乎所有其他情況下,類型參數被保留,如字段/參數/返回類型聲明。其中一個被保留的情況是而不是被刪除是一個類的超類。所以如果你創建一個擴展爲ArrayList<String>的類,你可以在運行時訪問這些信息。

但這似乎矯枉過正,不是嗎?一個延伸ArrayList<String>的新類和另一個延伸ArrayList<String>等的類似乎不切實際。匿名內部類可以使這更容易。所以,如果你想保留通用信息,你只需要做new ArrayList<String>() {}而不是new ArrayList<String>()。您可以在創建的對象上調用getClass().getGenericSuperclass()以獲取通用信息。

+0

我並不是想讓他們自己做,而是爲了恢復普通類型的用戶以序列化的形式傳輸對象...我想這是不可能的以適當的方式。一種盡力而爲的方法是檢查一個類是否使用泛型類型,如果是,檢查是否有內部使用它們的字段。使用實例和這些字段,可以重構使用的泛型類型。但對於我的工作,我猜這是一種矯枉過正的... –

+0

+1:這與[番石榴的'TypeToken']使用的技術相同(http://docs.guava-libraries.googlecode.com/git/的Javadoc/COM /谷歌/普通/反映/ TypeToken.html)。 –

+0

@IanRoberts是Guava使用相同的技術。我相信這是2006年最初在這個模式上發表過博文的Neal Gafter。他稱之爲[Super Type Tokens](http://gafter.blogspot.de/2006/12/super-type-tokens.html)模式。在我看來,Java社區有點低估了。 – Saintali