Java反射获取泛型相关信息
GenericArrayType
泛型数组,组成数组的元素中有范型则实现了该接口; 它的组成元素是ParameterizedType或TypeVariable类型,它只有一个方法:
Type getGenericComponentType(): 返回数组的组成对象
package com.enjoy.reflect.genericArrayType;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
public class GenericArrayTypeTest<T> {
List<String>[] lists;
public static void main(String[] args) {
//尝试获取数组lists的填充数据类型
Class clz = GenericArrayTypeTest.class;
try {
Field field = clz.getDeclaredField("lists");
//获取填充数组的数据类型
GenericArrayType type = (GenericArrayType) field.getGenericType();
Type arraytype = type.getGenericComponentType();//泛型数组的声明类型,包含泛型信息
System.out.println("====================="+arraytype);
//获取填充数组的数据类型,如果数据类型是泛型,那么获取的是承载泛型的对象的数据类型
ParameterizedType parameterizedType = (ParameterizedType) arraytype;
//parameterizedType.getRawType(),获取承载泛型的类信息
System.out.println("=============="+parameterizedType.getRawType());
//获取泛型的实际类型
for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) {
System.out.println("===========actualTypeArgument = "+actualTypeArgument);
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
运行结果如下:
ParameterizedType
ParameterizedType
具体的泛型类型, 如Map<String, String>
有如下方法:
Type getRawType(): 返回承载该泛型信息的对象, 如上面那个Map<String, String>承载范型信息的对象是Map
Type[] getActualTypeArguments(): 返回实际泛型类型列表, 如上面那个Map<String, String>实际范型列表中有两个元素, 都是String
package com.enjoy.reflect.parameterizedType;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
public class ParameterizedTypeTest {
Map<String,Integer> map;
public static void main(String[] args) throws Exception {
Field field = ParameterizedTypeTest.class.getDeclaredField("map");
System.out.println("==========GenericType = "+field.getGenericType());
ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
Type rawType = parameterizedType.getRawType();
System.out.println("========rawType = "+rawType);
//Map中泛型是2个,实际应用中,可能会有多个,所以是数组
Type[] typeArguments = parameterizedType.getActualTypeArguments();
for (Type typeArgument : typeArguments) {
System.out.println("=========== typeArgument = "+typeArgument);
System.out.println("=========== typeArgument.getTypeName = "+typeArgument.getTypeName());
}
}
}
运行结果:
TypeVariable
TypeVariable
泛型变量, 泛型信息在编译时会被转换为一个特定的类型, 而TypeVariable就是用来反映在JVM编译该泛型前的信息.
TypeVariable就是<T>、<C extends Collection>中的变量T、C本身; 它有如下方法:
Type[] getBounds(): 获取类型变量的上边界, 若未明确声明上边界则默认为Object
getGenericDeclaration(): 获取声明该类型变量的类型
String getName(): 获取在源码中定义时的名字
注意:
类型变量在定义的时候只能使用extends进行(多)边界限定, 不能用super;
为什么边界是一个数组? 因为类型变量可以通过&进行多个上边界限定,因此上边界有多个
package com.enjoy.reflect.typeVariable;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
public class TypeVariableTest<K extends Comparable & Serializable,V> {
K key;
V value;
public static void main(String[] args) throws Exception {
Field fk = TypeVariableTest.class.getDeclaredField("key");
Field fv = TypeVariableTest.class.getDeclaredField("value");
TypeVariable typeVariableK = (TypeVariable) fk.getGenericType();
TypeVariable typeVariableV = (TypeVariable) fv.getGenericType();
System.out.println("========== typeVariableK.name = "+typeVariableK.getName());
System.out.println("========== typeVariableV.name = "+typeVariableV.getName());
GenericDeclaration kDecla = typeVariableK.getGenericDeclaration();
GenericDeclaration vDecla = typeVariableV.getGenericDeclaration();
System.out.println("============ kDecla = "+kDecla);
System.out.println("============ VDecla = "+vDecla);
Type[] kbounds = typeVariableK.getBounds();
for (Type kbound : kbounds) {
System.out.println("========== kbound = "+kbound);
}
Type[] vbounds = typeVariableV.getBounds();
for (Type vbound : vbounds) {
System.out.println("========== vbound = "+vbound);
}
}
}
运行结果:
WildcardType
WildcardType
该接口表示通配符泛型, 比如? extends Number 和 ? super Integer 它有如下方法:
Type[] getUpperBounds(): 获取范型变量的上界
Type[] getLowerBounds(): 获取范型变量的下界
注意:现阶段通配符只接受一个上边界或下边界, 返回数组是为了以后的扩展, 实际上现在返回的数组的大小是1
package com.enjoy.reflect.wildcardType;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.WildcardType;
import java.util.List;
public class WildcardTypeTest {
private List<? extends Number> numbers;
private List<? super String> s;
public static void main(String[] args) throws Exception {
Field nf = WildcardTypeTest.class.getDeclaredField("numbers");
Field af = WildcardTypeTest.class.getDeclaredField("s");
//获取泛型参数类型
ParameterizedType nftype = (ParameterizedType) nf.getGenericType();
ParameterizedType aftype = (ParameterizedType) af.getGenericType();
//获取泛型通配符类型
WildcardType nfwType = (WildcardType) nftype.getActualTypeArguments()[0];
WildcardType afwType = (WildcardType) aftype.getActualTypeArguments()[0];
System.out.println("=============nfwType up"+nfwType.getUpperBounds()[0]);
// System.out.println("=============nfwType lower"+nfwType.getLowerBounds()[0]);//运行报错,extends限定的是上界,没有下界
// System.out.println("=============afwType up"+afwType.getUpperBounds()[0]);//运行报错,super限定的是下界,没有上界
System.out.println("=============afwType lower"+afwType.getLowerBounds()[0]);
}
}
运行结果:
以上几个类型都是继承是Type类的,java.lang.reflect.Type。
如果需要在反射的时候获取泛型相关的信息,就可以使用上述几个类达到目的。
举个例子:解析Gson数据为相应的Bean类。
首先有个TypeReference类,定义如下:
package com.enjoy.reflect.gson.type;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class TypeReference<T> {
Type type;
T t;
protected TypeReference(){
//注意.class和getClass的区别
/*两者的区别如下:
类名.class叫做“类字面量”,因class是关键字, 所以类名.class编译时确定。而getclass()是某个具体的方法来调用,是运行时根据实际实例确定,getClass()是动态而且是final的。
例如:
String.class 是能对类名的引用取得在内存中该类型class对象的引用,而new String().getClass() 是通过实例对象取得在内存中该实际类型class对象的引用。
*/
//这里注意getSuperclass和getGenericSuperclass的区别,
// getGenericSuperclass包含泛型信息,getSuperclass不包含泛型信息
Type genericSuperClz = getClass().getGenericSuperclass();
System.out.println("======= TypeReference genericSuperClz = "+genericSuperClz
+"\n=========type = "+getType()+"\n======.class = "+TypeReference.class);
ParameterizedType parameterizedType = (ParameterizedType) genericSuperClz;
//因为类泛型可以定义多个 A<T,E..> 所以是个数组
Type[] types = parameterizedType.getActualTypeArguments();
type = types[0];
}
public Type getType(){
return type;
}
}
然后有一个DeSerialized类,定义如下:
package com.enjoy.reflect.gson;
import com.enjoy.reflect.gson.type.TypeReference;
import com.google.gson.Gson;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class DeSerialized {
static class Response<T> {
T data;
int code;
String message;
@Override
public String toString() {
return "Response{" +
"data=" + data +
", code=" + code +
", message='" + message + '\'' +
'}';
}
public Response(T data, int code, String message) {
this.data = data;
this.code = code;
this.message = message;
}
/*public Type getType(){
Type type = null;
Type tempType = getClass().getGenericSuperclass();
System.out.println("==========tempType = "+tempType);
ParameterizedType parameterizedType = (ParameterizedType) tempType;
type = parameterizedType.getActualTypeArguments()[0];
System.out.println("==============response getType = "+type);
return type;
}*/
}
static class Data {
String result;
public Data(String result) {
this.result = result;
}
@Override
public String toString() {
return "Data{" +
"result=" + result +
'}';
}
}
public static void main(String[] args) {
Response<Data> response = new Response<>(new Data("Rayman"),888,"Yes");
// response.getType();
Gson gson = new Gson();
String json = gson.toJson(response);
System.out.println("========json = "+json);
//反序列化......
/**
* 有花括号: 代表是匿名内部类,创建一个匿名内部类的实例对象
* 没花括号:创建实例对象
* 如果创建的是实例对象,比如:Type type = new TypeReference<Response<Data>>().getType();
那么getClass().getGenericSuperclass()获取的Type是Object, 并不包含泛型信息;
* 必须是内部类匿名类,通过getClass().getGenericSuperclass()获取的Type才包含泛型信息
*/
Type type = new TypeReference<Response<Data>>(){}.getType();
System.out.println("=========type = "+type);
Response<Data> ret = gson.fromJson(json,type);
System.out.println("============ret = "+ret);
}
}
运行结果:
========json = {"data":{"result":"Rayman"},"code":888,"message":"Yes"}
======= TypeReference genericSuperClz = com.enjoy.reflect.gson.type.TypeReference<com.enjoy.reflect.gson.DeSerialized$Response<com.enjoy.reflect.gson.DeSerialized$Data>>
=========type = null
======.class = class com.enjoy.reflect.gson.type.TypeReference
=========type = com.enjoy.reflect.gson.DeSerialized$Response<com.enjoy.reflect.gson.DeSerialized$Data>
============ret = Response{data=Data{result=Rayman}, code=888, message='Yes'}
可以看到,这里借助辅助类TypeReference<T>成功的解析出来Gson中含有的泛型Bean类。
上一篇: AES加解密算法
下一篇: java使用反射获取泛型信息