大家好,欢迎来到IT知识分享网。
文章目录
1.Type类型
1.1 什么是Type?
Type是一个空接口,是所有类型的公共接口(父接口),其意义表示Java所有类型。这里所谓的类型是从Java整个语言角度来看的,比如原始类型、参数化类型(泛型)、类型变量及其数组等,可以理解为,Class(类)是Java对现实对象的抽象,而Type是对Java语言对象的抽象。
- GenericArrayType(泛型数组类型),
- ParmeterizedType(参数化类型),
- TypeVariable(类型变量),
- WildcardType(通配符类型)。
实现了Type接口的子类
- Class(类)。
1.2 Type的用处
由于java1.5引入了泛型这一概念,大大方便了我们代码的编写和优化,但是考虑到泛型擦除这一问题,当我们的代码在运行时期会擦除所有的泛型,这一我们在运行时期想要获取某一类原来是带有泛型的,而后来被擦除了的数据的泛型类型时就会有问题。所以java引入了Type这一概念。Type也主要是为在运行时期获取泛型而服务。
1.3 ParmeterizedType(参数化类型)的作用
ParameterizedType接口中常用的方法有三个,分别是: Type getRawType() 返回参数化类型中的原始类型,例如List<String>的原始类型为List Type[] getActualTypeArguments() 获取参数化类型的类型变量或者是实际类型列表,例如Map<Integer, String>的实际泛型列表Integer和String。改列表的所有类型都是Type,也即是说,可能存在多层嵌套的情况。 Type getOwnerType() 返回是类型所属的类型,例如存在A<T>,其中定义了内部类InnerA<T>,则InnerA<T>的所属类型是A<T>,如果是顶层类型则返回null,这种关系比较常见的是Map<K, V>接口与Map.Entry<K, V>接口,Map<K,V>接口是Map.Entry<K,V>接口的ownerType。
1.3.1 测试ParmeterizedType
@Test public void test() throws ClassNotFoundException, InstantiationException, IllegalAccessException { Class<TypeBean> bean = (Class<TypeBean>) Class.forName("com.noahgroup.supervise.TypeBean"); Field[] declaredFields = bean.getDeclaredFields(); int i = 1; for (Field field : declaredFields) { field.setAccessible(true); System.out.println("--------------" + i + "---------------"); System.out.println("field name is : " + field.getName()); System.out.print("field.getGenericType() instanceof ParameterizedType"); System.out.println("--------" + (field.getGenericType() instanceof ParameterizedType)); if (field.getGenericType() instanceof ParameterizedType) { ParameterizedType type = (ParameterizedType) field.getGenericType(); System.out.println("---------------ActualTypeArguments:---------------"); //获取范型的参数类型 Type[] actualTypeArguments = type.getActualTypeArguments(); for (Type t : actualTypeArguments) { System.out.println(t); } System.out.println("---------------ActualTypeArguments:---------------"); //获取 返回是类型所属的类型(内部类所属的类型),如果是顶层类型则返回null System.out.println("OwnerType=" + type.getOwnerType()); //获取 有范型的类 的原始类型 比如Map.Entry<T,R> ,是Map System.out.println("RawType=" + type.getRawType()); } if (field.getName().equals("animal")) { ParameterizedType type = (ParameterizedType) field.getGenericType(); Type ownerType = type.getOwnerType(); System.out.println("Person.Animal<String>的ownerType是" + ownerType); Type rawType = type.getRawType(); System.out.println("Person.Animal<String>的rawType是" + rawType); Type[] actualTypeArguments = type.getActualTypeArguments(); for (Type type2 : actualTypeArguments) { //System.out.println("type:" + ((Class)type2).newInstance().getClass());; System.out.println("Person.Animal<String>的actualTypeArguments是" + "获取到的actualTypeArguments分别为:" + type2.getTypeName()); } System.out.println("Person.Animal<String> instanceof ParameterizedType -----" + (type instanceof ParameterizedType)); } System.out.println("--------------" + i + "---------------"); System.out.println(""); i++; } } public class TypeBean<T> { // 1. 是 ParmeterizedType public List<String> list; // 2. 不是 ParmeterizedType private Set<String>[] set; // 3. 不是 ParmeterizedType private List noGerList; // 4. 是 ParmeterizedType Map.Entry<String, Integer> entry; //5. 是 ParmeterizedType Person.Animal<String> animal; //6. 不是 ParmeterizedType String str = new String(); //7. 不是 ParmeterizedType T t; //8. 是 ParmeterizedType public List<List<String>> doubleList; //9. 是 ParmeterizedType Class<T> classA; //10. 是 ParmeterizedType Class<?> classB; } public class Person { @Override public String toString() { return "Person []"; } class Animal<T> { public T name; } }
1.3.2 测试结果
- 第一个字段List list 是ParameterizedType。
- 第二个字段Set[] set由于是数组,所以不是ParameterizedType。
- 第三个字段List noGerList由于没有带泛型,所以也不是ParameterizedType。
- 第四个字段Map.Entry<String,Integer> entry 是parameterizedType。
- 第五个字段Person.Animal animal 是parameterizedType。此处我们进一步使用了ParameterizedType的3个方法演示给大家看。我们可以看到ownerType是animal的外部类Person。这也印证了获取到的类型(Person)为原类型(Person.Animal)是其(Person)成员之一。(这里还有其他情况欢迎在评论区告诉。)
而rawType则是其自身类型。
getActualTypeArguments()获取到的Type数组则是泛型中的所有类型。(例如Map<k,v>则获取到的数组中包含k,v这两个类型。并且k在前,v在后。) - 第六个字段String str = new String();由于没有带泛型所有不是parameterizedType。
- 第七个字段T t 由于是本类上定义的泛型,所以也不行。
--------------1--------------- field name is : list field.getGenericType() instanceof ParameterizedType--------true ---------------ActualTypeArguments:--------------- class java.lang.String ---------------ActualTypeArguments:--------------- OwnerType=null RawType=interface java.util.List --------------1--------------- --------------2--------------- field name is : set field.getGenericType() instanceof ParameterizedType--------false --------------2--------------- --------------3--------------- field name is : noGerList field.getGenericType() instanceof ParameterizedType--------false --------------3--------------- --------------4--------------- field name is : entry field.getGenericType() instanceof ParameterizedType--------true ---------------ActualTypeArguments:--------------- class java.lang.String class java.lang.Integer ---------------ActualTypeArguments:--------------- OwnerType=interface java.util.Map RawType=interface java.util.Map$Entry --------------4--------------- --------------5--------------- field name is : animal field.getGenericType() instanceof ParameterizedType--------true ---------------ActualTypeArguments:--------------- class java.lang.String ---------------ActualTypeArguments:--------------- OwnerType=class com.noahgroup.supervise.Person RawType=class com.noahgroup.supervise.Person$Animal Person.Animal<String>的ownerType是class com.noahgroup.supervise.Person Person.Animal<String>的rawType是class com.noahgroup.supervise.Person$Animal Person.Animal<String>的actualTypeArguments是获取到的actualTypeArguments分别为:java.lang.String Person.Animal<String> instanceof ParameterizedType -----true --------------5--------------- --------------6--------------- field name is : str field.getGenericType() instanceof ParameterizedType--------false --------------6--------------- --------------7--------------- field name is : t field.getGenericType() instanceof ParameterizedType--------false --------------7--------------- --------------8--------------- field name is : doubleList field.getGenericType() instanceof ParameterizedType--------true ---------------ActualTypeArguments:--------------- java.util.List<java.lang.String> ---------------ActualTypeArguments:--------------- OwnerType=null RawType=interface java.util.List --------------8--------------- --------------9--------------- field name is : classA field.getGenericType() instanceof ParameterizedType--------true ---------------ActualTypeArguments:--------------- T ---------------ActualTypeArguments:--------------- OwnerType=null RawType=class java.lang.Class --------------9--------------- --------------10--------------- field name is : classB field.getGenericType() instanceof ParameterizedType--------true ---------------ActualTypeArguments:--------------- ? ---------------ActualTypeArguments:--------------- OwnerType=null RawType=class java.lang.Class --------------10---------------
1.4 TypeVariable的作用
TypeVariable表示的是类型变量,它用来反映在JVM编译该泛型前的信息。例如List中的T就是类型变量,它在编译时需要被转换为一个具体的类型后才能被正常使用。该接口中有三个常用的方法,分别是:
Type[] getBounds() 获取类型变量的上边界,如果未声明上边界则默认是Object,例如UserService<T extends User>的上边界就是User。 D getGenericDeclaration() 获取声明该类型的原始类型,例如 UserService<T extends User>的原始类型就是UserService。 String getName() 获取在源码中定义时的名字,例如UserService<T extends User>中就为T。
1.5 GenericArrayType的作用
GenericArrayType表示的是数组类型且组成元素是ParameterizedType或者是TypeVariable,例如List[] 或 T[]。该接口只有 getGenericComponentType()一个方法,它返回数组的组成元素。
1.6 WildcardType的作用
WildcardType表示的是通配符泛型。WildcardType是依托于ParameterizedType和GenericArrayTypeTest而存在的。
示例如下: Class<?> List<? extends Number> Set<? super T>
WildcardType接口有两个方法,分别是: Type[] getUpperBounds() 返回泛型变量的上界。 Type[] getLowerBounds() 返回泛型变量的下界。
1.6.1 WildcardType测试
public class WildcardTypeBean<K extends Number & Serializable,V> { //1 是 GenericArrayType List<? extends Person>[] list; //2 是 ParameterizedType Set<? super Man> set; //3 是 TypeVariable K k; } public class WildcardTypeTest { public static void main(String[] args) throws Exception{ Field[] fields = WildcardTypeBean.class.getDeclaredFields(); for (int i = 0; i <fields.length; i++) { System.out.println("--------------"+(i+1)); Field field = fields[i]; System.out.println("file:"+field); Type type = field.getGenericType(); if(type instanceof GenericArrayType){ GenericArrayType gat = (GenericArrayType)type; ParameterizedType genericComponentType = (ParameterizedType)gat.getGenericComponentType(); Type[] actualTypeArguments = genericComponentType.getActualTypeArguments(); WildcardType t = (WildcardType)actualTypeArguments[0]; Type[] upperBounds = t.getUpperBounds(); for (Type type2 : upperBounds) { System.out.println("upperBounds:"+type2.getTypeName()); } Type[] lowerBounds = t.getLowerBounds(); for (Type type2 : lowerBounds) { System.out.println("lowerBounds:"+type2.getTypeName()); } }else if(type instanceof ParameterizedType){ WildcardType wildcardType = ((WildcardType)((ParameterizedType) type).getActualTypeArguments()[0]); Type[] lowerBounds = wildcardType.getLowerBounds(); for (Type type2 : lowerBounds) { System.out.println("lowerBounds:"+type2.getTypeName()); } }else{ System.out.println(type.getTypeName()+" instanceof "+type.getClass()); } System.out.println("--------------"+(i+1)); } }
1.6.2 测试结果
--------------1 file:java.util.List[] WildcardTypeBean.list upperBounds:Person --------------1 --------------2 file:java.util.Set WildcardTypeBean.set lowerBounds:Man --------------2 --------------3 file:java.lang.Number WildcardTypeBean.k K instanceof class sun.reflect.generics.reflectiveObjects.TypeVariableImpl --------------3
文章参考
- Type类型详解
- Type接口的基础知识
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/127651.html