在這個類中,有普通的String類型,有數組類型,有帶泛型的List類型,有嵌套List類型,以及有多個泛型參數的簡單類,這個類將做爲咱們後面的內容的基礎。咱們這一次博客解析如何使用反射獲取到不一樣屬性的類型值。java
public class Some{ private String name; private Integer[] numbers; private List<String> list; private List<List<Double>> matrix; private Map<String,Class> map; //ignore getter and setter }
普通類型的變量直接field.getType()便可以獲取到他們的類型數組
public void queryNameType() throws NoSuchFieldException { Field field = Some.class.getDeclaredField("name"); Class<?> type = field.getType(); assertEquals(type,String.class); }
數組類型不像其餘的類型能夠經過isAssignableFrom()函數來進行判斷,他須要使用isArray() 來判斷該type是不是一個數組類型,而後使用getComponentType() 獲取他的元素的類型函數
public void queryArrayType() throws NoSuchFieldException { Field field = Some.class.getDeclaredField("numbers"); Class<?> type = field.getType(); //通常來講,判斷是不是某種類型是可使用isAssignableFrom // 判斷是不是數組類型比較特殊,要使用isArray()這個函數 if (type.isArray()){ //得到數組的類型,使用getComponentType()這個方法 Class<?> componentType = type.getComponentType(); assertEquals(componentType,Integer.class); } else{ throw new IllegalStateException(); } }
帶泛型的類型就是相似於List<String>這樣的類型,咱們如今的任務就是獲取到String這個類型。
ParameterizedType表示參數化的類型,例如Collection這樣的類型。咱們能夠經過getGenericType()方法得到該子類,當你的類型帶有參數的時候就會返回ParameterizedType,不然會返回普通的類型(class)
那麼具體是怎麼操做的呢?
以得到List<T>的類型爲例子工具
public void getListType() throws NoSuchFieldException { Field field = Some.class.getDeclaredField("list"); //若是相似於List<String>這樣的類型就是一種GenericType //注意這是一種Type類型 Type type = field.getGenericType(); if (type instanceof ParameterizedType){ //泛型參數類型 ParameterizedType parameterizedType = (ParameterizedType)type; Type[] actualTypes = parameterizedType.getActualTypeArguments(); //由於List<String>得到第一個泛型參數,由於只有一個,咱們取第一個 //若是咱們有多個泛型參數,咱們能夠根據順序取不一樣的泛型參數 assertEquals(actualTypes[0],String.class); //若是得到List這個原始類型呢? assertEquals(parameterizedType.getRawType(),List.class); }else{ throw new IllegalStateException(); } }
假如是List<List<String>> 如何得到最裏面的類型呢?
例子以下ui
public void getSubListType() throws NoSuchFieldException { //思考一下,若是咱們有一個嵌套List,咱們想拿到嵌套在最裏面的類型,那麼咱們能夠這麼作呢? //其實咱們可使用遞歸的思想去得到最裏面的類型 Field field = Some.class.getDeclaredField("matrix"); assertEquals(getBaseType(field.getGenericType()),Double.class); } public static Type getBaseType(Type genericReturnType){ Objects.requireNonNull(genericReturnType); if (genericReturnType instanceof ParameterizedType && List.class.isAssignableFrom((Class)(((ParameterizedType) genericReturnType).getRawType()))){ Type[] actualTypeArguments = ((ParameterizedType)genericReturnType).getActualTypeArguments(); Type type = actualTypeArguments[0]; return getBaseType(type); }else{ return genericReturnType; } }
與第三個例子類似,只須要使用actualTypes數組按順序取便可
例子以下spa
public void getMapType() throws NoSuchFieldException { Field field = Some.class.getDeclaredField("map"); Type type = field.getGenericType(); if (type instanceof ParameterizedType){ ParameterizedType parameterizedType = (ParameterizedType)type; Type[] actualTypes = parameterizedType.getActualTypeArguments(); assertEquals(actualTypes[0],String.class); assertEquals(actualTypes[1],Class.class); }else{ throw new IllegalStateException(); } }
以上總結了幾種經常使用的使用反射獲取屬性類型的例子,稍加改造就能夠寫本身的工具類了。但願對你們有幫助^_^code