在讲阿里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个小忙: