我常常在文章或論壇中讀到全部的Java範型信息都會在編譯時搽除,因此不能在運行時訪問範型的任何信息。這並不徹底準確。某些案例下能夠在運行時訪問範型信息,這些案例實際上覆蓋了咱們對範型信息的一些需求。本文將解釋這些案例。html
使用範型一般有2種不一樣的場景:java
當你編寫一個類/接口時,能夠指定類/接口是否被參數化。這是java.util.List
接口的示例。你能夠參數化java.util.List
接口去建立一個String類型的list,而不是object list,以下:數組
List<String> myList = new ArrayList<String>();
當使用反射檢視可參數化類型自己時,好比java.util.List
,是沒有辦法獲得它的已參數化的類型的。object自身是不知道它參數化的類型的。
然而,object的reference
知道它包含的範型引用的類型信息。那就是,若是它不是局部變量。若是一個object被另外一個object的field
引用,你就能夠經過反射查看Field
定義,經過field
得到範型的類型信息。
同理,若是一個object被一個方法的參數引用。能夠經過方法的Parameter
,你能夠看到方法參數肯定範型的類型信息。
最後,你能夠經過方法返回值肯定反射範型信息。須要強調的是,實際返回object時你不能獲得範型信息。你須要經過反射查看方法定義,去得到方法定義的返回值(包含範型信息)。
總結起來就是:你只能經過object的引用查看它的範型信息,而不能經過它自身查看。
下面的部分將仔細研究這些狀況。學習
如你已得到java.lang.reflect.Method
對象,那麼就能夠得到它的返回值的範型。你能夠閱讀 "Java Generics: Methods"學習如何得到Method
對象。下面示例類的方法擁有一個可參數化的返回類型。this
public class MyClass { protected List<String> stringList = ...; public List<String> getStringList(){ return this.stringList; } }
在這個類中能夠得到方法getStringList()
的帶範型的返回類型。換言之,能夠發現方法getStringList()
返回List<String>
並不單單是List
。代碼以下:code
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[]
數組typeArguments
包含單個元素-java.lang.String
類的Class
實例。Class
實現了Type
接口。htm
你也能夠在運行時經過反射訪問方法的範型參數。下面示例類有一個方法擁有一個參數化List
做爲參數:對象
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包含單個元素-表明類
java.lang.String的
Class實例。
Class實現了
Type`接口。get
一樣的,咱們也能夠訪問公共屬性的範型類型。屬性是類的成員變量-不管靜態或實例變量。你能夠得到關於Field
的文章"Java Generics: Fields",下方是早些時候的示例代碼,擁有一個名爲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
包含的單元素-表明java.lang.String
類的Class
實例。Class
實現了Type
接口。