1 概述
- 开发过程中如果需要编写比较通用的代码时,经常需要使用到泛型;
- 但有时候会被无法获取到泛型类型而困扰,所以写下此篇作为笔记;
2 常用获取泛型类型方法
public class GenericTest {
public static void main(String[] args) {
// 1 false trag为E 错误获取方式。
List<String> list1 = new ArrayList<>();
list1.add("test1");
System.out.println(genericClassName(list1));
// 2 true trag为class java.lang.String 匿名内部类获取方式。
List<String> list2 = new ArrayList<String>() {
};
list2.add("test2");
System.out.println(genericClassName(list2));
// 3 true trag为class java.lang.String 额外传递匿名内部类获取方式,这种更为常见。
List<String> list3 = new ArrayList<>();
list3.add("test3");
System.out.println(genericClassName(list3, new TypeReference<String>() {
}));
}
/**
* 获取泛型类型
*
* @param list
* @param <T>
*/
private static <T> boolean genericClassName(List<T> list) {
Type type = list.getClass().getGenericSuperclass();
Type trag = ((ParameterizedType) type).getActualTypeArguments()[0];
T t = list.get(0);
return t.getClass().equals(trag);
}
/**
* 获取泛型类型(更为常见,如:RestTemplate、FastJson、Jackson、Gson都是采用这种方式)
* 额外入参变量来存储泛型类型来传递
*
* @param list
* @param <T>
*/
private static <T> boolean genericClassName(List<T> list, TypeReference<T> typeReference) {
Type type = typeReference.getClass().getGenericSuperclass();
Type trag = ((ParameterizedType) type).getActualTypeArguments()[0];
T t = list.get(0);
return t.getClass().equals(trag);
}
/**
* 自定义类型引用类
*/
static class TypeReference<T> {
}
}
3 源码:RestTemplate为例
public static void main(String[] args) {
RestTemplate restTemplate = new RestTemplate();
String url = "http://test.test.com";
HttpMethod method = HttpMethod.GET;
HttpEntity httpEntity = null;
ParameterizedTypeReference<Map<String, Object>> typeReference = new ParameterizedTypeReference<Map<String, Object>>(){};
Map<String, ?> uriVariables = null;
// public <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables)
ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(url, method, httpEntity, typeReference, uriVariables);
Map<String, Object> body = responseEntity.getBody();
}
- ParameterizedTypeReference类
public abstract class ParameterizedTypeReference<T> {
private final Type type;
protected ParameterizedTypeReference() {
// 与第2章节实现是类似,但对边界条件的检查更为全面,健壮性更好些
Class<?> parameterizedTypeReferenceSubclass = findParameterizedTypeReferenceSubclass(this.getClass());
Type type = parameterizedTypeReferenceSubclass.getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType)type;
this.type = parameterizedType.getActualTypeArguments()[0];
}
public Type getType() {
return this.type;
}
private static Class<?> findParameterizedTypeReferenceSubclass(Class<?> child) {
Class<?> parent = child.getSuperclass();
if (Object.class == parent) {
throw new IllegalStateException("Expected ParameterizedTypeReference superclass");
} else {
return ParameterizedTypeReference.class == parent ? child : findParameterizedTypeReferenceSubclass(parent);
}
}
}