最近在写一个本地缓存+Redis缓存的工具,主要实现就是请求来了先从本地缓存拿数据,如果本地缓存没有数据或者数据已过期,就从Redis中拿数据,如果Redis中没有数据,或者数据过期,则根据用户实现的子类实现的初始化方法拿到应该初始化的数据的功能,
由于缓存的子类实现有很多,而且每一个缓存的实现的返回类型等都不相同,所以在提供的获取方法时的返回值使用了泛型,而在Redis中存储数据时,由于不知道子类要缓存的具体数据类型是什么,所以就全部转成JSONString存储到Redis,这种就有一个问题,w为了方便使用,不可能提供一个返回String的方法,然后让使用者自己去强转成自己要的数据类型,所以我们需要自己实现将根据子类的不同返回不同类型的数据,由于泛型的类型擦除问题,我们不知道要返回的具体类型。最容易想到的问题,就是判断子类的类型,然后返回指定的类型,这种方式,太过死板,而且每增加一个子类实现,就需要自己的实现,完全没必要。后来就想到了下面的方法:
比如有四个类:
Test.java : 要返回的类型的实体类
import lombok.Data;
@Data
public class Test {
private String key;
private String value;
}
AbstractTest.java 我们提供方法的抽象类,提供了一个获取值得方法,返回类型为泛型 T
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
public abstract class AbstractTest<T> {
public T getValue(){
// //获取当前对象的父类class
// Type superClass = getClass().getGenericSuperclass();
// Type returnClass = null;
// if (superClass instanceof ParameterizedType) {
// // 把 Type 类型强制类型转换为 ParameterizedType 类型
// ParameterizedType parameterizedType = (ParameterizedType) superClass;
// // 获取对象
// returnClass = parameterizedType.getActualTypeArguments()[0];
// }
String value = "[{\"key\":\"test1\",\"value\":\"value1\"},{\"key\":\"test2\",\"value\":\"value2\"}]";
return JSONObject.parseObject(value,new TypeReference<T>(){});
};
}
TestImpl.java 子类实现类,继承了上述的抽象类,指定了泛型类型为List ,当然这个指定类型肯定有别的方式实现
import java.util.ArrayList;
import java.util.List;
public class TestImpl extends AbstractTest<List<Test>> {
}
main方法类,主要调用getValue方法
public class TestMain {
public static void main(String[] args) {
TestImpl impl = new TestImpl();
List<Test> ret = impl.getValue();
System.out.println(ret);
}
}
一般我们强转类型,可以使用alibaba的JSONObject.parseObject()方法,最开始我想的是使用
JSONObject.parseObject(value,new TypeReference<T>(){})
上面的方法是直接将T传入TypeReference内,最后发现,报错是不报错,但是返回的结果是List:
这种就不是我们想要的。后来改成:
Type superClass = getClass().getGenericSuperclass();
Type returnClass = null;
if (superClass instanceof ParameterizedType) {
// 把 Type 类型强制类型转换为 ParameterizedType 类型
ParameterizedType parameterizedType = (ParameterizedType) superClass;
// 获取对象
returnClass = parameterizedType.getActualTypeArguments()[0];
}
我们可以使用getActualTypeArguments获取类的指定的泛型类型数组,如果这个类有多个泛型的话,这个就是多个数据的数组,如果只有一个的话就取第一个就行了,我们就能拿到类型的Type,这时候再使用JSONObject强转就没问题了,如下图:



这种实现其实就是给大家一个思路,可以将原本返回泛型的数据,返回指定的类型