介绍
在Java中,泛型的使用非常广泛,但是在某些情况下,我们需要处理复杂的泛型类型,比如嵌套的泛型、带有通配符的泛型等。为了方便处理这些复杂的泛型类型,Fastjson提供了一个名为TypeReference
的工具类。TypeReference
类可以帮助我们在序列化和反序列化时,准确地指定复杂的泛型类型。它的主要作用是提供一个类型引用,以便在运行时获取泛型的实际类型信息。
1. TypeReference的使用
TypeReference
类的使用非常简单,只需要继承它,并实现一个匿名内部类,然后在构造函数中指定泛型类型即可。
1.1 使用TypeReference反序列化
先来定义一个Result类,也是一个泛型类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21class Result<T> {
private long code;
private T data;
public long getCode() {
return code;
}
public void setCode(long code) {
this.code = code;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
// 也可以使用Lombok
// @Data
// @AllArgsConstructor
}
再定义一个People类,以及它的get和set方法1
2
3
4
5
6
7
8
9
10class People {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
接下来实例化1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
Result<List<People>> result = new Result<>();
List<People> peopleList = new ArrayList<>();
// 设置Data
People xiaoHong = new People();
xiaoHong.setName("小红");
People xiaoMing = new People();
xiaoMing.setName("小明");
peopleList.add(xiaoHong);
peopleList.add(xiaoMing);
result.setData(peopleList);
// 设置code
result.setCode(0);
// 将对象转换为JSON字符串: 使用Fastjson的TypeReference
TypeReference<Result<List<People>>> typeReference = new TypeReference<Result<List<People>>>() {};
// 将对象转换为JSON字符串
String json = JSON.toJSONString(result);
输出对应的JSON字符串:1
2
3
4
5
6
7{
"code": 0,
"data": [
{ "name": "小红" },
{ "name": "小明" }
]
}
接下来使用TypeReference反序列化1
2
3
4
5
6
7
8
9
10
11
12
13
14import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import java.util.ArrayList;
String jsonStr = "{\"code\":0,\"data\":[{\"name\":\"小红\"},{\"name\":\"小明\"}]}";
TypeReference<Result<List<People>>> typeReference = new TypeReference<Result<List<People>>>() {};
ObjectMapper objectMapper = new ObjectMapper();
// 反序列化: 将JSON字符串转换为Result对象
Result<List<People>> listResult = objectMapper.readValue(jsonStr, typeReference);
System.out.println("Code: " + listResult.getCode());
System.out.println("Data: " + listResult.getData());
得到的输出结果:1
2Code: 0
Data: [{name=小红}, {name=小明}]
1.2 根据泛型动态构造TypeReference
假设我们提供了一个http客户端工具,它的定义是这样的1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35class HttpClient {
public String execute(String url, Map<String,Object> params) {
// 这里是模拟获取json字符串
return "{\"code\":0,\"data\":[{\"name\":\"小红\"},{\"name\":\"小明\"}]}";
}
public <T> T get(String url, Map<String,Object> params, TypeReference<T> typeR) {
String jsonStr = execute(url, params); // 获取jsonStr, 假设这里获取到的是前面的结果
// 解析为枚举类型,下面会讲解如何实现
ObjectMapper objectMapper = new ObjectMapper();
//在此处偷梁换柱(所谓的动态构造其实就一句话)
TypeReference<Result<T>> resultType = new TypeReference<Result<T>>() {
public Type getType() {
//在外层再包一层Result,就是所谓的动态构造
return new ParameterizedTypeImpl(new Type[]{typeR.getType()},null, Result.class); // 这里的Result是外层的泛型
}
};
Result<T> listResult = objectMapper.readValue(jsonStr, resultType);
// 异常判断
try {
if (listResult.getCode() != 0) {
throw new RuntimeException("请求失败");
}
} catch (Exception e) {
e.printStackTrace();
}
// 返回数据, 这里的listResult.getData()是List<People>类型
return listResult.getData();
}
}
调用样例1
2
3HttpClient client = new HttpClient();
//注意这里的TypeReference的泛型, 不是TypeReference<Result<List<People>>>, 没有Result
List<People> result = client.get("http://xxxx", params, new TypeReference<List<People>>());
2. TypeReference的实现原理
TypeReference
类的实现原理主要是通过Java的反射机制来获取泛型的实际类型信息。它使用了一个抽象类ParameterizedTypeImpl
,该类实现了ParameterizedType
接口,并重写了getActualTypeArguments()
方法,以返回实际的泛型参数类型。
ParameterizedType是一个记录类型泛型的接口, 继承自Type, 一共三方法:1
2
3
4
5public interface ParameterizedType extends Type {
Type[] getActualTypeArguments(); // 返回泛型类型数组
Type getRawType(); // 返回原始类型Type
Type getOwnerType(); // 返回 Type 对象,表示此类型是其成员之一的类型。
1 | import java.lang.reflect.ParameterizedType; |
参考文献
About this Post
This post is written by Rui Xu, licensed under CC BY-NC 4.0.