java在1.5版本引入了泛型(参数化类型),极大的方便了一些操作,使代码更加简洁。当然在泛型引入后,java反射机制也变得更加复杂化,这里就分享一些我对java泛型的研究。
获取泛型的方式:
field.getGenericType();//获得字段的泛型
method.getGenericParameterTypes();//获得方法参数的泛型
method.getGenericReturnType();//获得方法返回参数的泛型
method.getGenericExceptionTypes();//获得异常参数的泛型
class.getGenericInterfaces();//获得实现接口的泛型
class.getGenericSuperclass();//获得父类的泛型
...//待补充
已上所有获得泛型的方法返回的都是java.lang.reflect.Type,这个类有5个子类:ParameterizedType、GenericArrayType、WildcardType、TypeVariable、Class,以下一一说明这些子类是代表的什么。
1、ParameterizedType:有泛型的类型,举个例子:
public class Test14 {
Map<Integer, String> map;
public static void main(String[] args) {
try {
Field field = Test14.class.getDeclaredField("map");
Type type = field.getGenericType();//获得该字段的泛型
//已知map字段是一个java.util.Map且后面带有泛型,所以该Type是一个ParameterizedType
System.out.println("type instanceof ParameterizedType = " + (type instanceof ParameterizedType));
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] types = parameterizedType.getActualTypeArguments();
for (Type type1 : types) {
System.out.println(type1.getTypeName());
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
//输出结果:
type instanceof ParameterizedType = true
java.lang.Integer
java.lang.String
2、GenericArrayType:有泛型的类型且是数组,举个例子:
public class Test14 {
Map<Integer, String>[] map;
public static void main(String[] args) {
try {
Field field = Test14.class.getDeclaredField("map");
Type type = field.getGenericType();//获得该字段的泛型
//已知map字段是一个后面带有泛型的java.util.Map且是数组,所以该Type肯定是一个GenericArrayType
System.out.println("type instanceof GenericArrayType = " + (type instanceof GenericArrayType));
if (type instanceof GenericArrayType) {
GenericArrayType genericArrayType = (GenericArrayType) type;
Type type1 = genericArrayType.getGenericComponentType();
System.out.println(type1);
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
//输出结果:
type instanceof GenericArrayType = true
java.util.Map<java.lang.Integer, java.lang.String>
3、WildcardType,还需研究。
4、TypeVariable,还需研究。
5、Class,就是正常的class,不带泛型的。
当一个参数极端化时比如下面这个:
Map<String, Map<String, String[]>[]>[] map
解析起来会非常麻烦,我写了一个解析类,希望大家可以提出意见
public class ClassWithGenericType {
private Boolean isArray = false;
private String thisClass;
private ClassWithGenericType[] genericType;
public Boolean getIsArray() {
return isArray;
}
public void setIsArray(Boolean isArray) {
this.isArray = isArray;
}
public String getThisClass() {
return thisClass;
}
public void setThisClass(String thisClass) {
this.thisClass = thisClass;
}
public ClassWithGenericType[] getGenericType() {
return genericType;
}
public void setGenericType(ClassWithGenericType[] genericType) {
this.genericType = genericType;
}
public static ClassWithGenericType parseType(Type type) {
ClassWithGenericType cwgt = new ClassWithGenericType();
if (type instanceof GenericArrayType) {//有泛类型且是数组
GenericArrayType genericArrayType = (GenericArrayType) type;
cwgt = parseType(genericArrayType.getGenericComponentType());
cwgt.setIsArray(true);
} else if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
cwgt = parseType(parameterizedType.getRawType());
Type[] types = parameterizedType.getActualTypeArguments();
ClassWithGenericType[] cwgts = new ClassWithGenericType[types.length];
for (int i = 0; i < types.length; i++) {
Type actualType = types[i];
cwgts[i] = parseType(actualType);
}
cwgt.setGenericType(cwgts);
cwgt.setIsArray(false);
} else if (type instanceof WildcardType) {//TODO 需要研究
return cwgt;
} else if (type instanceof TypeVariable) {//TODO 需要研究
return cwgt;
} else if (type instanceof Class) {//无泛类型
Class clazz = (Class) type;
if (clazz.isArray()) {//数组类型
cwgt.setIsArray(true);
cwgt.setThisClass(clazz.getComponentType().getName());
} else {
cwgt.setIsArray(false);
cwgt.setThisClass(clazz.getName());
}
}
return cwgt;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(thisClass);
if (genericType != null && genericType.length > 0) {
sb.append("<");
StringBuilder sb2 = new StringBuilder();
for (ClassWithGenericType classWithGenericType : genericType) {
sb2.append(", ").append(classWithGenericType.toString());
}
sb.append(sb2.substring(2));
sb.append(">");
}
if (isArray)
sb.append("[]");
return sb.toString();
}
public String toJSON() {
return JSONObject.fromObject(this).toString();
}
public static ClassWithGenericType parseJson(String json) {
JSONObject jsonObject = JSONObject.fromObject(json);
return (ClassWithGenericType) JSONObject.toBean(jsonObject, ClassWithGenericType.class);
}
}
试验一下Map<String, Map<String, String[]>[]>[] map解析:
public class Test15 {
Map<String, Map<String, String[]>[]>[] map;
public static void main(String[] args) {
try {
Field field = Test15.class.getDeclaredField("map");
Type type = field.getGenericType();
System.out.println(ClassWithGenericType.parseType(type));
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
//输出结果:
java.util.Map<java.lang.String, java.util.Map<java.lang.String, java.lang.String[]>[]>[]
可以看到已经全部解析出来了。但是这个解析类还有一些问题:
1、extends 和 super 有问题,如下:
List<? extends TestBean> list1;
List<? super TestBean> list2;
//这一类的应该在WildcardType和TypeVariable中处理
2、在泛型继承的情况下有问题,如下:
public class Result<T> {
private Pager pager;
private List<T> list ;
public Pager getPager() {
return pager;
}
public void setPager(Pager pager) {
this.pager = pager;
}
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
public Result(Pager pager, List<T> list) {
this.pager = pager;
this.list = list;
}
public Result(){
}
}
//----
public static void main(String[] args) {
try {
Field field = Result.class.getDeclaredField("list");
Type type = field.getGenericType();
System.out.println(ClassWithGenericType.parseType(type));
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
//----
//输出结果
java.util.List<null>