先确定一点,也即泛型是在编译时就确定的。
任何在编译时不能确定的写法,最后尝试获取泛型子类时,可能获取的就是T,也即泛型标识符。
有如下代码:
interface callback<T> {
// 某个带泛型的接口
}
class callbackImpl<T> implements callback<T> {
// 如果在这个类中尝试获取泛型,那么要看编译时T是否是确定的。
}
public static void main(String[] args) {
// 由于这种方式是动态传入的泛型,在编译时并不知道具体的类型。 故在test方法中只能获取到T,而无法获取具体类型。
test(new callbackImpl<String>());
// 而加一个大括号这种写法相当于是定义匿名内部类,编译时可以确定类型为String。 可以通过clz.getGenericSuperclass()获取带泛型的类,从而获取泛型具体类型。
test(new callbackImpl<String>() {});
// 同理, 也相当于是定义一个匿名内部类, 编译时也可以确定类型为String,可以通过getGenericInterfaces()方法获取泛型类。
test(new callback<String>() {
});
}
// 测试方法
public void test(callback<?> p) {
Class<?> clz = p.getClass();
System.out.println("clz:" + clz);
System.out.println("clz:" + clz.getGenericSuperclass());
Type[] t = clz.getGenericInterfaces();
if (t != null && t.length != 0) {
System.out.println("clz interface: " + t.length);
for (int i = 0; i < t.length; i++) {
if (t[i] instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) t[i];
System.out.println("type is : " + parameterizedType.getActualTypeArguments()[0].getTypeName());
}
}
}
}
// 某个框架中的获取泛型的代码
public Object convert(Response apiResp) {
byte[] body = apiResp.getBody();
// 直接强转了。
ParameterizedType parameterizedType = (ParameterizedType)callback.getClass().getGenericInterfaces()[0];
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Type type = actualTypeArguments[0];
Object response = null;
Charset charset = apiResp.getCharset();
if (charset == null) {
charset = Charset.forName("UTF-8");
}
String text = new String(body, charset);
if (apiResp.getContentType() != null && apiResp.getContentType().contains("json")) {
response = JSON.parseObject(text, type, new Feature[0]);
} else {
response = JSON.parseObject(JSON.toJSONString(text), type, new Feature[0]);
}
return response;
}
关于泛型的获取,主要通过class类的getGenericInterfaces()方法及getGenericSuperclass()方法,其主要区别是一个是获取泛型接口,一个是获取泛型父类。
具体使用方法及说明可以参看启舰的博客。写的非常好,非常详细。