在这个类中,有普通的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