方法入参获取泛型类型

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);
        }
    }
}
posted @ 2021-07-06 22:00  月下小魔王  阅读(1751)  评论(0编辑  收藏  举报