0
点赞
收藏
分享

微信扫一扫

fastjson为何使用TypeReference?

小猪肥 2022-03-14 阅读 50


1 核心接口及类

fastJson​ 的泛型反序列化场景经常使用到 ​TypeReference​,如下示例:

public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");

JSONObject o = new JSONObject();
o.put("k",list);

List<String> types = o.getObject("k",List.class);
System.out.println(JSON.toJSONString(types));

List<String> types2 = o.getObject("k",new TypeReference<List<String>>(){});
System.out.println(JSON.toJSONString(types2));
}

使用TypeReference可明确指定反序列化的类型,如下

  • TypeReference构造器
    fastjson为何使用TypeReference?_泛型

1.1 ParameterizedType接口

ParameterizedType是一个记录类型泛型的接口, 继承自Type, 一共三接口


  1. Type[] getActualTypeArguments
    核心接口,返回泛型类型数组, 该接口可获取父类实际泛型类型,返回的Type数组对象表示该类型的实际类型参数。
  2. Type getRawType()
    返回原始类型Type
  3. Type getOwnerType()
    返回 Type 对象,表示此类型是其成员之一的类型。
    fastjson为何使用TypeReference?_泛型_02

比如 ​​Map<String,String>​​ 响应ParameterizedType三个接口的返回值如下:


  • [class java.lang.String, class java.lang.String]
  • interface java.util.Map
  • null

fastjson对其的实现类

fastjson为何使用TypeReference?_java_03

一般使用如下

new TypeReference<List<String>>(){}

创建一个​TypeReference​的匿名类,在其构造器中拿到泛型对应​Type(java.lang.reflect.ParameterizedType)​。

TypeReference的存在是因为java中子类可以获取到父类泛型的真实类型,为便于理解,看一段测试代码

public class TypeReferenceKest {

public static void main(String[] args) {
IntMap intMap = new IntMap();

System.out.println(intMap.getClass().getSuperclass());

Type type = intMap.getClass().getGenericSuperclass();
if(type instanceof ParameterizedType){
ParameterizedType p = (ParameterizedType) type;
for (Type t : p.getActualTypeArguments()){
System.out.println(t);
}
}

System.out.println("=====newclass=====");
HashMap<String,Integer> newIntMap = new HashMap<>();

System.out.println(newIntMap.getClass().getSuperclass());

Type newClassType = newIntMap.getClass().getGenericSuperclass();
if(newClassType instanceof ParameterizedType){
ParameterizedType p = (ParameterizedType) newClassType;
for (Type t : p.getActualTypeArguments()){
System.out.println(t);
}
}

System.out.println("=====subclass=====");
HashMap<String,Integer> subIntMap = new HashMap<String,Integer>(){};

System.out.println(subIntMap.getClass().getSuperclass());

Type subClassType = subIntMap.getClass().getGenericSuperclass();
if(subClassType instanceof ParameterizedType){
ParameterizedType p = (ParameterizedType) subClassType;
for (Type t : p.getActualTypeArguments()){
System.out.println(t);
}
}
}


public static class IntMap extends HashMap<String,Integer> {
}
}

输出为

class java.util.HashMap
class java.lang.String
class java.lang.Integer
=====newclass=====
class java.util.AbstractMap
K
V
=====subclass=====
class java.util.HashMap
class java.lang.String
class java.lang.Integer

获取到了实际类型,就可实现对泛型的反序列化。

Java虽然运行时会有类型擦除,但会保留Field的泛型信息,可通过​​Field.getGenericType()​​ 取字段的泛型。

public class FieldGenericKest {

public Map<String,Integer> map = new HashMap<>();
public List<Long> list = new ArrayList<>();

public static void main(String[] args) throws Exception {
FieldGenericKest kest = new FieldGenericKest();

Field map = kest.getClass().getField("map");
Field list = kest.getClass().getField("list");

System.out.println("=====map=====");
System.out.println("map.getType=" + map.getType());
System.out.println("map.getGenericType=" + map.getGenericType());

System.out.println("=====list=====");
System.out.println("list.getType=" + list.getType());
System.out.println("list.getGenericType=" + list.getGenericType());
}
}

输出

=====map=====
map.getType=interface java.util.Map
map.getGenericType=java.util.Map<java.lang.String, java.lang.Integer>
=====list=====
list.getType=interface java.util.List
list.getGenericType=java.util.List<java.lang.Long>

注意这里不能获取到字段的真实类型HashMap和ArrayList。

真实的类型当然不能用Field来获取,需要用对应的Value来获取

Object mapVal = map.get(kest);
if(mapVal != null){
Class<?> clz = mapVal.getClass();
System.out.println(mapVal.getClass().getName());
}

因为泛型的运行时擦除,对于局部变量来说, 泛型信息是无法获取的

参考

  • http://www.java2s.com/Tutorials/Java/java.lang/Class/Java_Class_getGenericSuperclass_.htm
  • https://zhaoyanblog.com/archives/186.html
  • https://developer.aliyun.com/article/609441


举报

相关推荐

0 条评论