前言
咋一看标题,你可能会说。不就是泛型吗,平时都使用着呢,没什么难的吧。
感觉了解了,但是真正的深入才知道自己了解甚少!
没有泛型的时候,只有原始类型。此时,所有的原始类型都通过字节码文件类Class类进行抽象。Class类的一个具体对象就代表一个指定的原始类型
泛型出现之后,扩充了数据类型。从只有原始类型扩充了参数化类型、类型变量类型、限定符类型 、泛型数组类型。
深入了解Java对类型的管理,对我们理解序列化、反序列化的深入理解讲非常有帮助。
类型的父类为Type,它位于反射包java.lang.reflect内。由JDK1.5之后提供的,它的标准继承图谱吐下:
(从左到右)依次是:GenericArrayType(数组类型)、ParameterizedType(参数化类型)、WildcardType( 泛型表达式类型)、TypeVariable(类型变量)、Class(原始/基本类型)
- Class(原始/基本类型,也叫raw type):不仅仅包含我们平常所指的类、枚举、数组、注解,还包括基本类型int、float等等
- TypeVariable(类型变量):比如List<T>中的T等
- WildcardType( 泛型表达式类型):例如List< ? extends Number>这种
- ParameterizedType(参数化类型):就是我们平常所用到的泛型List、Map(注意和TypeVariable的区别)
- GenericArrayType(数组类型):并不是我们工作中所使用的数组String[] 、byte[](这种都属于Class),而是带有泛型的数组,即T[] 泛型数组
Spring提供了更具统一的类型抽象:ResolvableType,但是本文只讲讲解JDK的
Type接口本身算是一个标记接口,不提供任何需要复写的方法
Type的直接子类只有一个,也就是Class,代表着类型中的原始类型以及基本类型。
public interface Type { default String getTypeName() { return toString(); } }
下面就专门针对这些类型做一些案例以及分析~
GenericArrayType
(数组类型)
泛型数组,描述的是形如:A< T>[]或T[]类型变量和原始类型
public interface GenericArrayType extends Type { //返回泛型数组中元素的Type类型,即List<String>[] 中的 List<String> Type getGenericComponentType(); }
demo:
public class GenericArrayTypeTest<T> { // 这里面有各种各样的数组:各有不同 方便看测试效果 // 含有泛型数组的才是GenericArrayType public void testGenericArrayType(List<String>[] pTypeArray, T[] vTypeArray, List<String> list, List<? extends Number> wildcardList, String[] strings, GenericArrayTypeTest[] test) { } public static void main(String[] args) { Method[] declaredMethods = GenericArrayTypeTest.class.getDeclaredMethods(); for (Method method : declaredMethods) { // main方法不用处理 if (method.getName().startsWith("main")) { continue; } // 开始处理该方法===打印出此方法签名 System.out.println("declare Method:" + method); //declare Method:public void com.fsx.maintest.GenericArrayTypeTest.testGenericArrayType(java.util.List[],java.lang.Object[],java.util.List,java.lang.String[],com.fsx.maintest.GenericArrayTypeTest[]) // 该方法能获取到该方法所有的实际的参数化类型,比如本例中有五个参数,那数组长度就是5 Type[] types = method.getGenericParameterTypes(); // 分组打印出来 for (Type type : types) { if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; System.out.println("ParameterizedType type :" + parameterizedType); } else if (type instanceof GenericArrayType) { // 从结果 GenericArrayType genericArrayType = (GenericArrayType) type; System.out.println("GenericArrayType type :" + genericArrayType); Type genericComponentType = genericArrayType.getGenericComponentType(); System.out.println("genericComponentType:" + genericComponentType); } else if (type instanceof WildcardType) { WildcardType wildcardType = (WildcardType) type; System.out.println("WildcardType type :" + wildcardType); } else if (type instanceof TypeVariable) { TypeVariable typeVariable = (TypeVariable) type; System.out.println("TypeVariable type :" + typeVariable); } else { Class clazz = (Class) type; System.out.println("type :" + clazz); } } } } }
输出结果:
declare Method:public void com.fsx.maintest.GenericArrayTypeTest.testGenericArrayType(java.util.List[],java.lang.Object[],java.util.List,java.util.List,java.lang.String[],com.fsx.maintest.GenericArrayTypeTest[]) GenericArrayType type :java.util.List<java.lang.String>[] genericComponentType:java.util.List<java.lang.String> GenericArrayType type :T[] genericComponentType:T ParameterizedType type :java.util.List<java.lang.String> ParameterizedType type :java.util.List<? extends java.lang.Number> type :class [Ljava.lang.String; type :class [Lcom.fsx.maintest.GenericArrayTypeTest;
分析:GenericArrayType有两个都是:List<String>[] pTypeArray, T[] vTypeArray它哥俩都是泛型数组。但是这两String[] strings, Main[] test可不是,他俩属于Class普通类型
genericArrayType.getGenericComponentType()返回的类型为ParameterizedTypeImpl类型,能够获取到数组的实际参数类型
ParameterizedType(参数化类型)
参数化类型,即泛型;例如:List< T>、Map< K,V>等带有参数化的对象。
public interface ParameterizedType extends Type { //获取类型内部的参数化类型 比如Map<K,V>里面的K,V类型 Type[] getActualTypeArguments(); // 类的原始类型,一般都是Class Type getRawType(); // 获取所有者类型(只有内部类才有所有者,比如Map.Entry他的所有者就是Map),若不是内部类,此处返回null Type getOwnerType(); }
demo:
public class ParameterizedTypeTest { private Map<String, ParameterizedTypeTest> map; private Set<String> set1; private Class<?> clz; private Holder<String> holder; private List<String> list; private ArrayList<String> arrayList; private Map.Entry<String, String> entry; private String str; private Integer i; private Set set; private List aList; static class Holder<V> { } public static void main(String[] args) { Field f = null; try { // 拿到所有的字段 Field[] fields = ParameterizedTypeTest.class.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { f = fields[i]; if (f.getGenericType() instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) f.getGenericType(); System.out.println(f.getName() + ":"); System.out.println("\t ParameterizedType:" + Arrays.asList(parameterizedType.getActualTypeArguments())); System.out.println("\t getRawType:" + parameterizedType.getRawType()); System.out.println("\t getOwnerType:" + parameterizedType.getOwnerType()); } // 输出不是ParameterizedType 参数化类型的 else { System.out.println(f.getName() + ":is not ParameterizedType "); } } } catch (Exception e) { } } }
输出:
map: ParameterizedType:[class java.lang.String, class com.fsx.maintest.ParameterizedTypeTest] getRawType:interface java.util.Map getOwnerType:null set1: ParameterizedType:[class java.lang.String] getRawType:interface java.util.Set getOwnerType:null clz: ParameterizedType:[?] getRawType:class java.lang.Class getOwnerType:null holder: ParameterizedType:[class java.lang.String] getRawType:class com.fsx.maintest.ParameterizedTypeTest$Holder getOwnerType:class com.fsx.maintest.ParameterizedTypeTest list: ParameterizedType:[class java.lang.String] getRawType:interface java.util.List getOwnerType:null arrayList: ParameterizedType:[class java.lang.String] getRawType:class java.util.ArrayList getOwnerType:null entry: ParameterizedType:[class java.lang.String, class java.lang.String] getRawType:interface java.util.Map$Entry getOwnerType:interface java.util.Map str:is not ParameterizedType i:is not ParameterizedType set:is not ParameterizedType aList:is not ParameterizedType
先看最后几个is not..的。发现即使是List,但是我们没给与泛型,它不会是ParameterizedType参数化类型。
然后holder和entry的getOwnerType不是null,因为他俩类型都是内部类,所以有所有者类型。其它的top类都是null
getRawType其实就是返回了本类的本来的Class类型
getActualTypeArguments:获取到泛型类型,返回一个数组(因为可能会有多个)