方法入參獲取泛型類型


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);
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM