原文地址:http://tutorials.jenkov.com/java-reflection/generics.html
========================================================================================
我經常在一些文章和論壇中看有人說Java泛型信息都會在編譯時被擦除,所以你不能在運行時訪問任何相關的信息。這也不完全對。在運行時,在少數情況下也是可以訪問到泛型信息的。實際上,這些情況中已經滿足了我們對Java泛型信息的需求。本文將解釋這幾種情況。
下面是本文所涵蓋的主題列表:
- The Generics Reflection Rule of Thumb ()
- Generic Method Return Type (方法返回值類型的泛型)
- Generic Method Parameter Types (方法參數類型的泛型)
- Generic Field Types (字段類型的泛型)
========================================================================================
- The Generics Reflection Rule of Thumb
使用Java泛型無外乎就下面兩種情況中的一種:
- Declaring a class/interface as being parameterizable. (聲明類、接口參數化)
- Using a parameterizable class.(使用參數化的類)
當你寫一個類或者接口的時候,你可以指定它可以被參數化。java.util.List接口就是這種用法。你可以使java.util.List參數化的創建一個String的列表,而不是創建一個Object的列表。
當在運行時檢查參數化類型它自己的類型時,如java.util.List,沒有辦法知道它具體被參數化成了什么類型。這樣也合理,因為在同一應用程序中參數化的類型可以是所有類型。但是,當你檢查用參數化類型聲明的方法或者字段時,你可以知道它們在運行時參數化成了什么類型。簡而言之:
在運行時,你不會知道參數化類型它自己的類型,但是你能知道用了參數化類型的字段和方法的類型。換句話說,它們有具體的參數類型。
下面的部分我們將更進一步的來看這幾種情況。
========================================================================================
- Generic Method Return Types
如果你獲得了java.lang.reflect.Method對象,你也是有可能獲得它的返回值類型的泛型信息的。這不會是任何參數化類型的Method對象,除了在類里面使用了參數化類型。你可以去看“Java泛型:方法”來了解如何獲取Method對象。下面是一個例子,類中有參數化返回值類型的返回值:
public class MyClass { protected List<String> stringList = ...; public List<String> getStringList(){ return this.stringList; } }
在這種情況下,可以取得getStringList()方法的泛型返回值類型。換句話說,是可以檢測到getStringList()方法返回的是List<String>類型而不僅僅是List。下面是如何來取:
Method method = MyClass.class.getMethod("getStringList", null); Type returnType = method.getGenericReturnType(); if(returnType instanceof ParameterizedType){ ParameterizedType type = (ParameterizedType) returnType; Type[] typeArguments = type.getActualTypeArguments(); for(Type typeArgument : typeArguments){ Class typeArgClass = (Class) typeArgument; System.out.println("typeArgClass = " + typeArgClass); } }
這段代碼將會打印出“typeArgClass = java.lang.String”.Type[ ]類型的數組typeArguements中包含一個項——一個代表實現了Type接口的java.lang.String.Class的Class實例。
========================================================================================
- Generic Method Parameter Types
在運行時,你也可以用Java反射機制訪問泛型參數的類型。下面是一個例子,類里面有一個參數化類型的參數:
public class MyClass { protected List<String> stringList = ...; public void setStringList(List<String> list){ this.stringList = list; } }
你可以像這樣來訪問其方法參數的參數化類型:
method = Myclass.class.getMethod("setStringList", List.class); Type[] genericParameterTypes = method.getGenericParameterTypes(); for(Type genericParameterType : genericParameterTypes){ if(genericParameterType instanceof ParameterizedType){ ParameterizedType aType = (ParameterizedType) genericParameterType; Type[] parameterArgTypes = aType.getActualTypeArguments(); for(Type parameterArgType : parameterArgTypes){ Class parameterArgClass = (Class) parameterArgType; System.out.println("parameterArgClass = " + parameterArgClass); } } }
這段代碼將會打印出“parameterArgType = java.lang.String”。Type[ ]類型的數組parameterArgTypes中包含一個項——一個代表實現了Type接口的java.lang.String.Class的Class實例。
========================================================================================
- Generic Field Types
也可以訪問公有字段的泛型類型。字段是類的成員變量——要么是靜態變量,要么是實體變量。你可以去看“Java泛型:字段”來了解如何獲取Field對象。下面是一個很早之前的例子,類中有有一個叫stringList的實體字段:
public class MyClass { public List<String> stringList = ...; }
Field field = MyClass.class.getField("stringList"); 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”。Type[ ]類型的fieldArgTypes數組中包含一個項——一個代表實現了Type接口的java.lang.String.Class的Class實例。
========================================================================================
- 目錄
這是一個本教程到目前為止涵蓋的主題列表:
- Java反射——引言
- Java反射——Class對象
- Java反射——構造函數
- Java反射——字段
- Java反射——方法
- Java反射——Getter和Setter
- Java反射——私有字段和私有方法
- Java反射——注解
- Java反射——泛型
- Java反射——數組
- Java反射——動態代理
- Java反射——類的動態加載和重新加載
(敬請期待下一篇翻譯)