泛型的实际类型获取在写底层基础类的时候,经常会用到,这里将Spring4中关于泛型获取的API归纳整理如下
public class BaseService<T> {
}
public interface CustomService<T, K, U> {
}
如果是一个很抽象没有加任何限定的泛型,那么是获取不到的。
当然如果是实现了接口或者继承了某个类,那么是可以获取到具体的泛型类型的。
public class CustomServiceImpl
extends BaseService<List<String>>
implements CustomService<List<Map<String, Integer>>,
BaseService<List<Map<String,Integer>>>,
BaseService> {
}
public class GenericTest {
public static void main(String[] args) {
//获取到 CustomServiceImpl 这个类的Type
ResolvableType oriType = ResolvableType.forClass(CustomServiceImpl.class);
//获取父类,就是extends的那个类,因为java是单继承,所以只会有一个
ResolvableType superType = oriType.getSuperType();
System.out.println(superType.resolve()); // class com.zzhua.service.BaseService
System.out.println(superType.getGeneric(0).resolve()); // interface java.util.List
//获取CustomServiceImpl这个类要实现的接口,因为接口可能会有多个,所以是一个数组
ResolvableType[] interfaces = oriType.getInterfaces();
for (ResolvableType interfaceResolvableType : interfaces) {
System.out.println(interfaceResolvableType.resolve()); // interface com.zzhua.service.CustomService
}
// 开始进行泛型获取,
// 接口定义: public interface CustomService<T, K> {}
// 通过最复杂的:CustomServiceImpl implements CustomService<List<Map<String, Integer>>, BaseService> 举例
ResolvableType generic1 = interfaces[0].getGeneric(0);
System.out.println(generic1.toString()); // java.util.List<java.util.Map<java.lang.String, java.lang.Integer>>
System.out.println(generic1.resolve()); // interface java.util.List
ResolvableType generic2 = interfaces[0].getGeneric(1); // BaseService
System.out.println(generic2.toString()); // com.zzhua.service.BaseService<?>
System.out.println(generic2.resolve()); // class com.zzhua.service.BaseService
// 第一个0表示获取的是:Map<String, Integer> ,第二个0表示获取的String
ResolvableType generic0_0 = generic1.getGeneric(0, 0);
System.out.println(generic0_0.resolve()); // class java.lang.String
ResolvableType generic0_1 = generic1.getGeneric(0, 1);
System.out.println(generic0_1.resolve()); // class java.lang.Integer
// 所以通过以上示例, 可以知道
// 1. 先去拿具体的类的ResolvableType,
// 2. 具体的类可以拿到它的 父类的ResolvableType(只会有1个父类), 所有实现接口的ResolvableType(可能会有多个)
// 3. 继续通过拿到的ResolvableType, 调用它的getGeneric(int... indexes), 里面可传多个参数(表示在泛型中的位置,从0开始)
// class java.lang.String
System.out.println(ResolvableType.forClass(CustomServiceImpl.class).getInterfaces()[0].getGeneric(1, 0, 0, 0).resolve());
// class java.lang.Integer
System.out.println(ResolvableType.forClass(CustomServiceImpl.class).getInterfaces()[0].getGeneric(1, 0, 0, 1).resolve());
// class com.zzhua.service.BaseService
System.out.println(ResolvableType.forClass(CustomServiceImpl.class).getInterfaces()[0].getGeneric(2).resolve());
// CustomServiceImpl的第三个泛型BaseService没有写明具体的泛型类, 因此这里是null
System.out.println(ResolvableType.forClass(CustomServiceImpl.class).getInterfaces()[0].getGeneric(2, 0).resolve());
}
}
public class GenericInjectTest {
private Map<String, Map<String, Integer>> map;
// ....
public Map<String, Map<String, Integer>> methodName() {
return null;
}
}
如果要获取某个字段的泛型,那么可以采用:
ResolvableType resolvableType4 = ResolvableType.forField(ReflectionUtils.findField(GenricInjectTest.class, "map"));
resolvableType4.getGeneric(1).getGeneric(1).resolve();
// class java.lang.Integer
ResolvableType resolvableType5 = ResolvableType.forMethodReturnType(ReflectionUtils.findMethod(GenricInjectTest.class, "methodName"));
System.out.println(resolvableType5.getGeneric(1, 0).resolve());
// class java.lang.String