您需要了解
TypeReference作品的运作方式。为此,我们进入源代码
protected TypeReference(){ Type superClass = getClass().getGenericSuperclass(); if (superClass instanceof Class<?>) { // sanity check, should never happen throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information"); } ... _type = ((ParameterizedType) superClass).getActualTypeArguments()[0];}该
Class#getGenericSuperclass()javadoc的状态
返回表示该类表示的实体的直接超类的Type(类,接口,原始类型或void)。
如果超类是参数化类型,则返回的Type对象必须准确反映源代码中使用的实际类型参数。
换句话说,如果我们能够做到
newTypeReference()(我们不能做到,那是抽象的),它将返回
Class该类的实例
Object。但是,使用匿名类(从类型扩展)
new TypeReference<String>(){}创建的实例的直接超类是参数化类型
TypeReference,根据javadoc,我们应该获得一个
Type实例,该实例可以
准确反映源代码中使用的实际类型参数 :
TypeReference<String>
然后您可以从中获得参数化类型
getActualTypeArguments()[0]),并返回
String。
让我们以使用匿名类和子类进行可视化为例
public class Subclass<T> extends TypeReference<AgentResponse<T>>{ public Subclass() { System.out.println(getClass().getGenericSuperclass()); System.out.println(((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]); }}跑步
new Subclass<String>();
版画
com.fasterxml.jackson.core.type.TypeReference<Test.AgentResponse<T>>Test.AgentResponse<T>
符合javadoc规则。
Test.AgentResponse<T>是源代码中实际的参数化类型。现在,如果相反,我们有
new Subclass<String>(){}; // anonymous inner class我们得到结果
Test.Subclass<java.lang.String>class java.lang.String
这也符合要求。现在,内部类直接从源类中扩展了,该内部类
Subclass由其参数进行参数化
String。
您会注意到,使用
Subclass匿名内部类,我们丢失了有关
AgentResponse泛型类型的信息。这是不可避免的。
注意
reader = new StringReader("{"element":{"map-element":[{"name":"soto", "value": 123}]}}");obj = mapper.readValue(reader, new AgentReq<Map<String, Set<Whatever>>>());将编译并运行,但是类型
AgentReq<Map<String,Set<Whatever>>>将丢失。Jackson将使用默认类型来序列化JSON。的
element将被反序列化作为
AgentResponse,而
map-element将被反序列化作为
Map和JSON数组作为
ArrayList。



