更新时间:2023-11-26 14:14:28
你需要了解一个 TypeReference
有效。为此,我们进入源代码
You need to understand how a TypeReference
works. For that we go into the source code
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 states
The Class#getGenericSuperclass()
javadoc states
返回表示实体
(类,接口,基本类型或void)的直接超类的Type )由本课程代表。
Returns the Type representing the direct superclass of the entity (class, interface, primitive type or void) represented by this Class.
如果超类是参数化类型,返回的$对象
必须准确反映源
代码中使用的实际类型参数。
If the superclass is a parameterized type, the Type object returned must accurately reflect the actual type parameters used in the source code.
换句话说,如果我们可以做 new TypeReference()
(我们可以' t,它是抽象的),它将为类 Object
返回 Class
实例。但是,使用匿名类(从类型扩展)
In other words, if we could do new TypeReference()
(we can't, it's abstract), it would return the Class
instance for the class Object
. However, with anonymous classes (which extend from the type)
new TypeReference<String>(){}
创建的实例的直接超类是参数化类型 TypeReference
和根据javadoc,我们应该得到 Type
实例准确反映源代码中使用的实际类型参数:
the direct superclass of the instance created is the parameterized type TypeReference
and according to the javadoc we should get a Type
instance that accurately reflect the actual type parameters used in the source code:
TypeReference<String>
然后您可以使用获取参数化类型getActualTypeArguments()[0 ])
,返回字符串
。
from which you can then get the parameterized type with getActualTypeArguments()[0])
, returning String
.
让我们举一个例子来使用匿名类进行可视化并使用子类
Let's take an example to visualize using anonymous class and using a sub-class
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>
是源代码中的实际参数化类型。现在,如果相反,我们已经
which fits the javadoc rules. Test.AgentResponse<T>
is the actual parameterized type in the source code. Now, if instead, we had
new Subclass<String>(){}; // anonymous inner class
我们得到的结果
Test.Subclass<java.lang.String>
class java.lang.String
这也适合账单。内部类现在直接从 Subclass
扩展,它在源代码中使用参数 String
进行参数化。
which also fits the bill. The inner class now extends directly from Subclass
which is parameterized with the argument String
in the source code.
您会注意到,使用 Subclass
匿名内部类,我们已经丢失了有关 AgentResponse的信息
泛型类型。这是不可避免的。
You will notice that, with the Subclass
anonymous inner class, we've lost information about the AgentResponse
generic type. This is unavoidable.
请注意
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。 元素
将被反序列化为 AgentResponse
,而 map-element
将被反序列化为 Map
,而JSON数组将被反序列为 ArrayList
。
will compile and run, but the type AgentReq<Map<String, Set<Whatever>>>
will have been lost. Jackson will use default type to serializes the JSON. The element
will be deserialized as an AgentResponse
, while map-element
will be deserialized as a Map
and the JSON array as an ArrayList
.