在講阿里fastjson 以前,先講下泛型的一些基礎知識和在反射中如何獲取泛型,以爲本身已經掌握的能夠直接經過目錄跳到最後查看java
泛型類的定義只要在申明類的時候,在類名後面直接加上< E>,中的E能夠是任意的字母,也能夠多個,多個用逗號隔開就能夠。示例代碼以下面試
public class SelfList<E> {}
複製代碼
那麼何時肯定這個E 的具體類型呢?實際上是在new 一個對象的時候指定的,請看下面代碼redis
public class SelfList<E> {
public void add(E e) {
if (e instanceof String) {
System.out.println(" I am String");
} else if (e instanceof Integer) {
System.out.println("I am Integer");
}
}
public static void main(String[] args) {
//這裏建立的時候指定了String
SelfList<String> a = new SelfList<String>();
a.add("123");
//這裏建立的時候指定了Integer
SelfList<Integer> b = new SelfList<Integer>();
b.add(123);
}
}
複製代碼
泛型接口和類的使用方式同樣json
public interface IndicatorTypeService<T> {}
//這裏定義的時候指定具體類型爲ProductSale,固然也能夠這裏沒有指定具體類型
public class ProductSaleServiceImpl implements IndicatorTypeService<ProductSale> {}
複製代碼
這個我以爲是相對來講比較可貴,你們集中注意力聽我說,說不定你之前一直覺得的泛型方法是假的。好,先給個假的泛型方法給你們驗一下,仍是上面代碼的例子,爲了方便閱讀我再貼一遍代碼小程序
//注意這是個假的泛型方法,不要覺得有一個E就是泛型方法哦
public void add(E e) {
if (e instanceof String) {
System.out.println(" I am String");
} else if (e instanceof Integer) {
System.out.println("I am Integer");
}
}
複製代碼
好了,重點來了,給個真正的泛型方法定義出來數組
public <T> T get(T t) {
return t;
}
複製代碼
public <T> T get(T t) {
return t;
}
public static void main(String[] args) {
//這裏建立的時候指定了String
SelfList<String> a = new SelfList<String>();
a.add("123");
int num = a.get(123);
}
複製代碼
那麼泛型方法是怎麼肯定這個具體類型的呢? 主要思想是在調用該泛型方法傳進去的參數類型和返回值類型來肯定具體類型的bash
public <T> T get1(T t) {
if (t instanceof String) {
System.out.println(" I am String");
} else if (t instanceof Integer) {
System.out.println("I am Integer");
}
return t;
}
public static void main(String[] args) {
SelfList<String> a = new SelfList<String>();
//這裏調用的時候傳進去的是int 類型,因此肯定了他的類型是int
int b=a.get1(123);
}
複製代碼
輸出結果測試
I am Integer
複製代碼
public <T> T get2(T t, T t2) {
if (t instanceof Float) {
System.out.println(" I am String");
} else if (t instanceof Integer) {
System.out.println("I am Integer");
} else if (t instanceof Number) {
System.out.println("I am Number");
}
return t;
}
public static void main(String[] args) {
SelfList<String> a = new SelfList<String>();
//這裏返回值類型必須是number 類型
Number b = a.get2(123, 12.1);
}
複製代碼
注意上面的輸出還會是ui
I am Integer
複製代碼
由於根據第一條規則,傳進去的是什麼類型就是什麼類型,可是返回值類型候須要根據第二條規則來肯定spa
上面說的都是在編譯以前就能夠肯定的泛型。你們知道,泛型運行的時候實際上是會被擦除的。不過不要緊,仍是提供給咱們經過反射的方式來獲取。首先我來認識下java中的泛型類型繼承結構
public interface ParameterizedType extends Type {
/**
* 返回一個實際類型的數組
* 好比對於ArrayList<T>,被實例化的時候ArrayList<String>,這裏返回的就是String
*
*/
Type[] getActualTypeArguments();
/**
* 這裏其實就是返回去掉泛型後的真實類型
* 對於List<T> 這裏返回就是List
*/
Type getRawType();
/**
* 這裏針對的是內部類的狀況,返回的是他的外層的類的類型
* 例如SelfHashMap 裏面有一個Entry 內部類,也就是SelfHashMap.Entry<String,String>
* 返回的就是SelfHashMap
*/
Type getOwnerType();
}
複製代碼
定義一個有內部類的類
public class SelfHashMap {
public static class Entry<T, V extends Collection> {
}
}
複製代碼
public class ParameterizedTypeTest {
public static void main(String[] args) {
Class clazz = A.class;
//注意這裏是拿父類的泛型,jdk 沒有提供本類的泛型
Type type = clazz.getGenericSuperclass();
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
System.out.println(Arrays.toString(parameterizedType.getActualTypeArguments()));
System.out.println(parameterizedType.getRawType());
System.out.println(parameterizedType.getOwnerType());
}
}
/**
* 這裏的泛型被是指定了爲String 和List
* getActualTypeArguments() 會輸出 String 和List
*/
public static class A extends SelfHashMap.Entry<String, List> {
}
}
複製代碼
輸出結果
[class java.lang.String, interface java.util.List]
class com.wizhuo.jdklearning.reflect.dto.SelfHashMap$Entry
class com.wizhuo.jdklearning.reflect.dto.SelfHashMap
複製代碼
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
/**
* 這裏返回的是泛型的上界類型數組,好比 <T, V extends Collection> 這裏的上界類型就是Collection
*/
Type[] getBounds();
/**
* 返回的是聲明該泛型變量的類,接口,方法等
* 列如 public static class Entry<T, V extends Collection> 返回的就是Entry
*/
D getGenericDeclaration();
/**
* 這裏返回的就是泛型定義的變量名稱,好比 <T> 返回的就是T
*
*/
String getName();
/**
* 這裏返回的就是AnnotatedType 數組,jdk1.8 才加進來,本文不分析,直接跳過
*/
AnnotatedType[] getAnnotatedBounds();
}
複製代碼
public class TypeVariableTest {
public static void main(String[] args) {
Class clazz = SelfHashMap.Entry.class;
TypeVariable[] typeVariables = clazz.getTypeParameters();
for (TypeVariable ty :typeVariables) {
System.out.println(ty.getName());
System.out.println(Arrays.toString(ty.getAnnotatedBounds()));
System.out.println((Arrays.toString(ty.getBounds())));
System.out.println(ty.getGenericDeclaration());
System.out.println("============================");
}
}
}
複製代碼
輸出的結果
T
[sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@3fee733d]
[class java.lang.Object]
class com.wizhuo.jdklearning.reflect.dto.SelfHashMap$Entry
============================
V
[sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@5acf9800]
[interface java.util.Collection]
class com.wizhuo.jdklearning.reflect.dto.SelfHashMap$Entry
複製代碼
看到下面這段代碼,簡單的意思就是從redis 獲取字符串,而後轉換爲指定的泛型的類。你們能夠留意到這裏建立了個TypeReference 匿名類 注意後面是有帶{}的,因此是實例化一個匿名內部類(這是重點中的重點,一切的魔術從這裏開始),而不是TypeReference 這個類的實例
List<ResourceEntity> resources =
redisAdapter.get(BaseConstant.TENANT_CODE_SYSTEM, CacheKey.KEY_ALL_RESOURCE,
new TypeReference<List<ResourceEntity>>() {
});
複製代碼
點進去看看這個源碼
protected final Type type;
/** *注意這裏protected ,也就意味着咱們建立的時候只能繼承這個類成爲他的子類,畢竟咱們的類 * 不可能和阿里巴巴的fastjson 在同一個包目錄下 * * 通常咱們都是建立一個匿名內部類來成爲他的子類,而後泛型中傳進咱們想要轉化的最終泛型 * 例如上面的代碼new TypeReference<List<ResourceEntity>>() {} List<ResourceEntity> 是咱們想要轉化的類型 * * */
protected TypeReference(){
//這裏是獲取父類的泛型,因爲jdk 不支持獲取本身的泛型,這裏巧妙的經過繼承這個類,變成獲取父類的泛型來解決
Type superClass = getClass().getGenericSuperclass();
//這裏返回泛型的實際類型,就是 List<ResourceEntity>
type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
複製代碼
若是你以爲這篇內容對你挺有啓發,我想邀請你幫我2個小忙: