雖然這是事實,Java將在刪除類型(因此將List<String>
變成List
),在很多情況下,它實際上會在運行時存儲通用類型,從而允許您恢復丟失的信息。 您可以檢索實際泛型類型爲這些:
- 方法參數(你的情況)
- 方法的返回類型
- 字段類型
- 超類/接口
這意味着,如果你只是有一個List類型的對象,沒有什麼可以做到的,以獲得它的通用類型(object.getClass()
會讓你List
就是這樣) - 它已經pe永久失落。但是,如果您試圖找出方法參數的泛型類型或以上任何一種,則通常使用反射可以使用。至於你的情況不涉及類型變量或其他併發症,這是非常簡單的,以獲得實際類型:如果你有多個參數和地圖,而不是
ParameterizedType listArgument = (ParameterizedType) ClassDeclaringFoo.class.getMethod("foo", List.class).getGenericParameterTypes()[0];
Type listType = listArgument.getActualTypeArguments()[0]; //This will be a Class representing String, the type of the List
:
public String foo(Object bar, Map<String, Number> possibleFoos) { ... }
代碼將與此類似:
ParameterizedType mapArgument = (ParameterizedType) ClassDeclaringFoo.class.getMethod("foo", Object.class, Map.class).getGenericParameterTypes()[1]; //1 is the index of the map argument
Type keyType = mapArgument.getActualTypeArguments()[0]; //This will be a Class representing String, the type of the Map key
Type valType = mapArgument.getActualTypeArguments()[1]; //This will be a Class representing Number, the type of the Map value
它是安全的假設這是DWR使用爲好,因爲類型是方法的參數。
類似的方法也可用於其他上市情況:
Class.getMethod(...).getGenericReturnType()
將讓你真正的返回類型
Class.getField(fieldName).getGenericType()
將讓你真正的類型的字段的
Class.getGenericSuperClass()
將讓你真正的超級型號
Class.getGenericInterfaces()
將爲您帶來真實的接口類型
分
等同的方法存在允許在Java中8引入訪問AnnotatedType
(通用型加註解的類型使用):
Class.getMethod(...).getAnnotatedParameterTypes()
Class.getMethod(...).getAnnotatedReturnType()
Class.getField(fieldName).getAnnotatedType()
Class.getAnnotatedSuperClass()
Class.getAnnotatedInterfaces()
現在,當你的案例與例子一樣簡單時,這一切都很華麗。 但是,試想一下,如果你的例子是這樣的:
public T foo(List<T> possibleFoos) {...}
在這種情況下,getGenericParameterTypes()[0].getActualTypeArguments()[0]
會給你T
這是相當無用的。爲了解決T
代表什麼,你必須查看類定義,也許是超類,同時跟蹤每個類中類型變量的命名方式,因爲每個類中的名稱可能不同。
爲了與普通的反射式操作更容易,你可以用一個精彩的庫調用GenTyRef,做了艱苦的工作適合你,如果你需要AnnotatedType
的支持下,你可以使用我的叉子稱爲GeAnTyRef(都是在Maven中中央)。他們還包括一個類型工廠,允許您構建(Annotated)Type
的實例,使用普通的Java API無法輕鬆完成實例。還有一個方便的super type token實現允許您獲得(Annotated)Type
文字。
有了這些,你可以用泛型類型的一切,Java允許沒有我上面所解釋的麻煩:
GenericTypeReflector#getExactParameterTypes(...)
GenericTypeReflector#getExactReturnType(...)
GenericTypeReflector#getExactFieldType(...)
GenericTypeReflector#getExactSuperType(...)
而且更多的操作,如figuri如果其中一個Type
是另一個超類型(類似於Class#isAssignableFrom
,但是泛型類型),則解析特定類型變量等。
謝謝您的全面回答,那正是我想知道的! – Radim
我使用了「hassle」版本,它對列表工作正常,但它不適用於map,因爲getParameterizedType返回類對象。由於我對以前的文章有了更好的瞭解,我試圖再次搜索如何使用地圖,但我沒有找到任何東西。你能再幫我一次嗎? – Radim
@Radim我已經更新了我的答案,以包含一個具有Map作爲第二個參數的示例。 那是你在追求什麼? –
kaqqao