最近在看retrofit2源码,框架的大致原理就是在okhttp的基础上利用注解和动态代理自动生成okhttp的request,抽象地理解就是利用注解表示请求体。在源码中看到里面有很多Java泛型,通过反射去获取泛型信息。如果说要看懂反射的泛型代码,那必须对泛型有足够的了解,其中Java 泛型 Type体系可是重中之重。
Type体系中Type接口是最顶层接口,用于表示JAVA的类型,包括 raw types(声明的类型), parameterized types(参数化类型), array types(范型数组), type variables (类型变量)and primitive types(基本类型)。其中primitive types是指基本类型, 包括boolean, byte, short, int, long,char, float,double,注意不包括String类型。
Type的直接继承子接口有四个:
ParameterizedType (参数化类型)
TypeVariable(类型变量)
GenericArrayType(范型数组)
WildcardType(通配符的类型)
UML如图所示
一、ParameterizedType (参数化类型)
形如 Collection<String> 或者Map<String,User> map声明的类型
接口方法:
Type[] getActualTypeArguments();
获取泛型中的参数,声明如Map<String,User> map 拿到String,User这两个参数的类型
Type getRawType();
获取声明的原始类型,如Map<String,User> map 拿到的是Map类型
Type getOwnerType();
获取所属类型,如Map.Entry<String, String > entry; 拿到的是Map类型,如果没有则返回null
测试代码:
public class TestType {
public static void main(String[] args) {
testParameterizedType();
// testTypeVariable();
// testGenericArrayType();
// testWildCardType();
}
public static class TestParameterizedBean {
// 下面的 field 的 Type 属于 ParameterizedType
Map<String, TestParameterizedBean> map;
Set<String> set1;
Class<?> clz;
Holder<String> holder;
List<String> list;
// Map<String,TestParameterizedBean> map 这个 ParameterizedType 的 getOwnerType() 为 null,
// 而 Map.Entry<String, String> entry 的 getOwnerType() 为 Map 所属于的 Type。
Map.Entry<String, String> entry;
// 下面的 field 的 Type 不属于ParameterizedType
String str;
Integer i;
Set set;
List aList;
}
public static void testParameterizedType() {
Field f = null;
try {
Field[] fields = TestParameterizedBean.class.getDeclaredFields();
// 打印出所有的 Field 的 TYpe 是否属于 ParameterizedType
for (int i = 0; i < fields.length; i++) {
f = fields[i];
System.out.println(f.getName()+" type is "+f.getGenericType().getTypeName());
System.out.println(
"------- is ParameterizedType ? "
+ (f.getGenericType() instanceof ParameterizedType));
if (f.getGenericType() instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) f.getGenericType();
System.out.println("------- rawType is " + pType.getRawType());
//获取泛型的声明参数 Map<T,K> map; 则getActualTypeArguments()是拿到T,k组成的数组
//getRawType() 则是interface java.util.Map
//getOwnerType()如 Map.Entry<String, String> entry;则拿到的是interface java.util.Map
for (Type type : pType.getActualTypeArguments()) {
System.out.println("------- getActualTypeArguments is " + type);
}
System.out.println("------- getOwnerType() is " + pType.getOwnerType()); // null
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
输出结果:
map type is java.util.Map<java.lang.String, main.TestType$TestParameterizedBean>
------- is ParameterizedType ? true
------- rawType is interface java.util.Map
------- getActualTypeArguments is class java.lang.String
------- getActualTypeArguments is class main.TestType$TestParameterizedBean
------- getOwnerType() is null
set1 type is java.util.Set<java.lang.String>
------- is ParameterizedType ? true
------- rawType is interface java.util.Set
------- getActualTypeArguments is class java.lang.String
------- getOwnerType() is null
clz type is java.lang.Class<?>
------- is ParameterizedType ? true
------- rawType is class java.lang.Class
------- getActualTypeArguments is ?
------- getOwnerType() is null
holder type is javax.xml.ws.Holder<java.lang.String>
------- is ParameterizedType ? true
------- rawType is class javax.xml.ws.Holder
------- getActualTypeArguments is class java.lang.String
------- getOwnerType() is null
list type is java.util.List<java.lang.String>
------- is ParameterizedType ? true
------- rawType is interface java.util.List
------- getActualTypeArguments is class java.lang.String
------- getOwnerType() is null
entry type is java.util.Map.java.util.Map$Entry<java.lang.String, java.lang.String>
------- is ParameterizedType ? true
------- rawType is interface java.util.Map$Entry
------- getActualTypeArguments is class java.lang.String
------- getActualTypeArguments is class java.lang.String
------- getOwnerType() is interface java.util.Map
str type is java.lang.String
------- is ParameterizedType ? false
i type is java.lang.Integer
------- is ParameterizedType ? false
set type is java.util.Set
------- is ParameterizedType ? false
aList type is java.util.List
------- is ParameterizedType ? false
二、TypeVariable(类型变量)
如声明为T t 的变量,其中T在class中声明定义
接口方法:
Type[] getBounds();
得到上边界的 Type数组,如类为TypeVariableBean< extends InputStream & Closeable, V>,则返回的是 K 的上边界数组 InputStream 和 Serializable。 V 没有指定的话, 默认上边界是 Object
D getGenericDeclaration();
返回的是声明这个 Type 所在的类 的 Type
String getName();
返回Type的名字
AnnotatedType[] getAnnotatedBounds();
返回注解类型的上边界数组,与getBounds()类似
测试代码:
public class TestType {
public static void main(String[] args) {
// testParameterizedType();
testTypeVariable();
// testGenericArrayType();
// testWildCardType();
}
private static void testTypeVariable() {
TypeVariableBean bean = new TypeVariableBean<FileInputStream, String>();
Field[] fields = bean.getClass().getDeclaredFields();
// 打印出所有的 Field 的 TYpe 是否属于 TypeVariable
Field f = null;
for (int i = 0; i < fields.length; i++) {
f = fields[i];
System.out.println(f.getName()
+ " is TypeVariable ? "
+ (f.getGenericType() instanceof TypeVariable));
if (f.getGenericType() instanceof TypeVariable) {
TypeVariable typeVariable = (TypeVariable) f.getGenericType();
System.out.println(typeVariable.getGenericDeclaration() + " TypeVariable");
System.out.println("边界类型:");
for (Type t : typeVariable.getBounds()) {
System.out.println( t.getTypeName());
}
}
}
}
public static class TypeVariableBean<K extends InputStream & Closeable, V> {
// K 的上边界是 InputStream
K key;//TypeTypeVariable
// 没有指定的话 ,V 的 上边界 属于 Object
V value;//TypeTypeVariable
// 不属于 TypeTypeVariable
V[] values; //GenericArrayType
String str;// PrimitiveType
List<K> kList;//ParameterizedType
}
}
输出结果
key the type is K
------- is TypeVariable ? true
-------GenericDeclaration is class main.TestType$TypeVariableBean
-------边界类型:
------- java.io.InputStream
------- java.io.Closeable
value the type is V
------- is TypeVariable ? true
-------GenericDeclaration is class main.TestType$TypeVariableBean
-------边界类型:
------- java.lang.Object
values the type is V[]
------- is TypeVariable ? false
str the type is class java.lang.String
------- is TypeVariable ? false
kList the type is java.util.List<K>
------- is TypeVariable ? false
三、GenericArrayType(范型数组)
变量声明形如的T[] genericArray; 或者List<String>[] array 的类型
接口方法
Type getGenericComponentType();
获取泛型数组中的元素的类型
测试代码
public class TestType {
public static void main(String[] args) {
// testParameterizedType();
// testTypeVariable();
testGenericArrayType();
// testWildCardType();
}
//GenericArrayType测试
// 简单来说就是:范型数组,组成数组的元素中有范型则实现了该接口;
// 它的组成元素是 ParameterizedType 或 TypeVariable 类型
public static class GenericArrayTypeBean<T> {
// 属于 GenericArrayType
List<String>[] pTypeArray;//组成元素是ParameterizedType类型的List<String>
// 属于 GenericArrayType
T[] vTypeArray;//组成元素是 TypeVariable 类型的T
// 不属于 GenericArrayType
List<String> list;//ParameterizedType类型
// 不属于 GenericArrayType
String[] strings;//正常类型
// 不属于 GenericArrayType
int[] ints;//正常类型
}
public static void testGenericArrayType() {
Field[] fields = GenericArrayTypeBean.class.getDeclaredFields();
Field f = null;
for (int i = 0; i < fields.length; i++) {
f = fields[i];
System.out.println(f.getName() + " the type is " + f.getGenericType());
System.out.println(
"-------- is GenericArrayType ? "
+ (f.getGenericType() instanceof GenericArrayType));
if (f.getGenericType() instanceof GenericArrayType) {
GenericArrayType type = (GenericArrayType) f.getGenericType();
//getGenericComponentType()是获取泛型数组中的元素的类型
System.out.println("--------数组元素是 "+type.getGenericComponentType().getTypeName());
}
}
}
}
输出结果:
pTypeArray the type is java.util.List<java.lang.String>[]
-------- is GenericArrayType ? true
--------数组元素是 java.util.List<java.lang.String>
vTypeArray the type is T[]
-------- is GenericArrayType ? true
--------数组元素是 T
list the type is java.util.List<java.lang.String>
-------- is GenericArrayType ? false
strings the type is class [Ljava.lang.String;
-------- is GenericArrayType ? false
ints the type is class [I
-------- is GenericArrayType ? false
四、WildcardType(通配符的类型)
参数声明中包含?通配符的类型。如List<?>,List<? extends Number>,List<? super Number> 这些类型 都属于WildcardType
extends 用来指定上边界,没有指定的话上边界默认是 Object, super 用来指定下边界,没有指定的话为 null.
接口方法:
Type[] getUpperBounds();
得到上边界 Type 的数组,如List<? extends Number>,返回的上边界Type是数组 是 {Number全类名}
Type[] getLowerBounds();
得到下边界 Type 的数组,如List<? super Number> ,返回的是下边界数组是{Number全类名}
默认情况下没有指定的话,上边界默认是 Object ,下边界是空。
测试代码
public class TestType {
public static void main(String[] args) {
// testParameterizedType();
// testTypeVariable();
// testGenericArrayType();
testWildCardType();
}
public static void testWildCardType() {
try {
Field[] fields = WildcardTypeBean.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
Type type = field.getGenericType();
String nameString = field.getName();
System.out.println(nameString + " the type is " + field.getGenericType());
if (!(type instanceof ParameterizedType)) {
System.out.println("-----不是ParameterizedType类型,没有通配符");
continue;
}
System.out.println("-----获取声明参数");
ParameterizedType parameterizedType = (ParameterizedType) type;
//获取声明参数
type = parameterizedType.getActualTypeArguments()[0];
System.out.println("-----声明参数getActualTypeArguments()[0] type is "+parameterizedType.getTypeName());
if (!(type instanceof WildcardType)) {
System.out.println("-----不是WildcardType");
continue;
}
WildcardType wildcardType = (WildcardType) type;
Type[] lowerTypes = wildcardType.getLowerBounds();
if (lowerTypes != null) {
System.out.println("-----下边界");
if (lowerTypes != null) {
for (Type t :
lowerTypes) {
System.out.println("-----"+t.getTypeName());
}
}
}
Type[] upTypes = wildcardType.getUpperBounds();
if (upTypes != null) {
System.out.println("-----上边界:");
for (Type t : upTypes) {
System.out.println("-----"+t.getTypeName());
}
}
System.out.println("---------------------------");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static class WildcardTypeBean {
private List<? extends Number> a; // a没有下界,
// 没有指定的话,上边界默认是 Object ,下边界是 String
private List<? super String> b;
private List<String> c;//类型参数中没有WildcardType类型
private Class<?> aClass;//默认有上边界 Object,无默认下边界
}
}
输出结果
a the type is java.util.List<? extends java.lang.Number>
-----获取声明参数
-----声明参数getActualTypeArguments()[0] type is java.util.List<? extends java.lang.Number>
-----下边界
-----上边界:
-----java.lang.Number
---------------------------
b the type is java.util.List<? super java.lang.String>
-----获取声明参数
-----声明参数getActualTypeArguments()[0] type is java.util.List<? super java.lang.String>
-----下边界
-----java.lang.String
-----上边界:
-----java.lang.Object
---------------------------
c the type is java.util.List<java.lang.String>
-----获取声明参数
-----声明参数getActualTypeArguments()[0] type is java.util.List<java.lang.String>
-----不是WildcardType
aClass the type is java.lang.Class<?>
-----获取声明参数
-----声明参数getActualTypeArguments()[0] type is java.lang.Class<?>
-----下边界
-----上边界:
-----java.lang.Object
---------------------------