java的Type设计分析
在1.5
版本后,java设计了Type,但是对于Type是什么一直也是和清晰,所以一起看一下吧。分析的方式采用UML类图的方式,进行功能设计的解释说明。
设计分析
-
Type接口
这个接口是所有类型的超类,只有一个没有很大作用的
getTypeName()
的默认方法,默认返回toString。 -
GenericArrayType接口
是一个数组类型接口,它的元素是
ParameterizedType
或者TypeVariable
。只有一个方法,返回数组元素的类型。
举例:public static void main(String[] args) { List<String> list = new ArrayList<>(); List<List<String>> strList = new ArrayList<>(); String[] strArr = new String[]{}; // cannot create generic array type but can use field or method get generic type List<String>[] listArr = new List[1]; listArr[0] = Lists.newArrayList("11"); System.out.println("list===>" + isGenericArrayType(list.getClass().getGenericInterfaces())); System.out.println("strList===>" + isGenericArrayType(strList.getClass().getGenericInterfaces())); System.out.println("str==>" + isGenericArrayType(strArr.getClass().getGenericInterfaces())); System.out.println("listArr==>" + isGenericArrayType(listArr.getClass().getGenericInterfaces())); Method method = GenericArrayTypeBean.class.getDeclaredMethods()[0]; System.out.println(method); // public void test(List<String>[] pTypeArray, T[] // vTypeArray,List<String> list, String[] strings, Person[] ints) Type[] types = method.getGenericParameterTypes(); // 这是 Method 中的方法 for (Type type : types) { System.out.println(type instanceof GenericArrayType);// 依次输出true,true,false,false,false } } private static boolean isGenericArrayType(Type[] types) { return Stream.of(types).anyMatch(type -> type instanceof GenericArrayType); } public class GenericArrayTypeBean<T> { public void test(List<String>[] pTypeArray, T[] vTypeArray, List<String> list, String[] strings) { } } list===>false strList===>false str==>false listArr==>false public void com.jd.xstore.stock.center.biz.stock.schedule.JdBuyStockNumChangeSchedule$GenericArrayTypeBean.test(java.util.List[],java.lang.Object[],java.util.List,java.lang.String[]) true true false false
-
WilcardType
通配符的类型,经常的用法是
?
,? extends
,? super
等。有两个方法,getUpperBounds
和getLowerBounds
Type[] getUpperBounds()
返回的是一个上限类型数组。如果没有声明,那么上限是Object
。Type[] getLowerBounds()
返回是一个下限类型数组。没有声明,返回长度为0的数组。
public static void main(String[] args) { List<? extends String> list = new ArrayList<>(); isWildcardType(list.getClass().getGenericInterfaces()); Field[] declaredFields = GenericBean.class.getDeclaredFields(); Arrays.stream(declaredFields).forEach(field -> { Type genericType = field.getGenericType(); if (genericType instanceof ParameterizedType) { Arrays.stream(((ParameterizedType) genericType).getActualTypeArguments()).forEach(type -> System.out.println(type.getTypeName() + ": " + (type instanceof WildcardType))); } System.out.println(field.getName() + ": " + (genericType instanceof WildcardType)); }); } private static void isWildcardType(Type[] types) { for (Type type : types) { if (type instanceof ParameterizedType) { Type actualTypeArgument = ((Parameterize dType) type).getActualTypeArguments()[0]; System.out.println(actualTypeArgument.getTypeName() + ": " + (actualTypeArgument instanceof WildcardType)); } } } public class GenericBean { private List<? extends String> list; private List<String> strList; } E: false ? extends java.lang.String: true list: false java.lang.String: false strList: false this$0: false
-
ParameterizedType
这个是比较常见的类型,但是并没说指定的很明白。个人理解是如果Class可以接受可变类型,这里以T来表示,
Class<T>
这种就是参数泛型。Type[] getActualTypeArguments()
获取T的真正类型,Type getRawType()
返回Class类型。比如List<String>
返回java.util.List
。
这个示例就略了。上述都有判断
ParameterizedType
的。 -
TypeVariable
这个官方给的解释很多,我们这里可以理解Class和方法中的T
,V
就是TypeVariable。个人觉得可以理解为类型用来标志泛型的变量,可以有上下限public static void main(String[] args) { List<? extends String> list = new ArrayList<>(); isTypeVariable(list.getClass().getGenericInterfaces()); Field[] declaredFields = GenericBean.class.getDeclaredFields(); Arrays.stream(declaredFields).forEach(field -> { Type genericType = field.getGenericType(); if (genericType instanceof ParameterizedType) { Arrays.stream(((ParameterizedType) genericType).getActualTypeArguments()).forEach(type -> System.out.println(type.getTypeName() + ": " + (type instanceof TypeVariable))); } System.out.println(field.getName() + ": " + (genericType instanceof TypeVariable)); }); Method[] methods = GenericBean.class.getMethods(); Arrays.stream(methods).forEach(m -> { Type[] genericParameterTypes = m.getGenericParameterTypes(); Arrays.stream(genericParameterTypes).forEach(type -> System.out.println(m.getName() + ":" + type.getTypeName() + (type instanceof TypeVariable))); }); } private static void isTypeVariable(Type[] types) { for (Type type : types) { if (type instanceof ParameterizedType) { Type actualTypeArgument = ((ParameterizedType) type).getActualTypeArguments()[0]; System.out.println(actualTypeArgument.getTypeName() + ": " + (actualTypeArgument instanceof TypeVariable)); } } } public class GenericBean<T> { private List<? extends String> list; private List<String> strList; public void test(T t) { } public <V> void test2(V v) { } } E: true ? extends java.lang.String: false list: false java.lang.String: false strList: false this$0: false test:Ttrue test2:Vtrue
-
GenericDeclaration
A common interface for all entities that declare type variables.
GenericDeclaration接口继承了AnnotatedElement接口,是所有“可以声明(定义)范型变量”的实体的公共接口。也就是说只有实现了这个接口的才能在对应“实体”上声明TypeVariable。目前实现实体有Class
,Method
,Constructor
.- 只有一个方法
getTypeParameters
获取TypeVariable<?>[]
例子:
public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); System.out.println(Arrays.toString(((GenericDeclaration) map.getClass()).getTypeParameters())); } [K, V]
- 只有一个方法
Type类型还是很抽象的,还是以后继续了解。资料也不很多。
在梳理的过程中,发现了以下的问题:
Type类型如何获取?
GenericDeclaration是通过获取Class,Method,Constructor的class进行获取的。
GenericArrayType不能直接实例化,只能通过method或者field的genericType进行获取
WildcardType同GenericArrayType
ParameterizedType 是Collection<E>
实现类,实现类的getClass的type就可以。也可以实例化,但是实例化后获取不到对应的泛型,只能获取到泛型变量
TypeVariable 这个是class中才可以获取到的。
为什么
List<String>
会instanceofParameterizedType
如何实现的?
待填坑
最后说一句,因为要兼容的原因,Type在运行时会被擦除。就先到这里,各位晚安