从几天前开始,我开始从事Web服务项目。该项目正在使用 Jackson 来编组和取消编组 JSON对象。所以我的问题是:
为什么在创建{}
的实例时总是必须放置TypeReference
?我知道构造函数是protected
,但是为什么是protected
?我认为这就像黑客一样,因为TypeReference
是abstract
,您可以做到这一点,使构造函数可见并创建该构造函数的实现。但是,这有什么意义呢?
String jsonString = "{\" firstName\":\"John\",\"lastName\":\"Chen\"}";
ObjectMapper objectMapper = new ObjectMapper();
// properties will store name and value pairs read from jsonString
Map<String, String> properties = objectMapper.readvalue(
jsonString, new TypeReference<Map<String, String>>()
{ //
});
答案 0 :(得分:6)
通过子类化,TypeReference
可以提取 actual 泛型类型参数。例如:
TypeReference<String> ref = new TypeReference<String>(){};
System.out.println(ref.getType());
打印:
class java.lang.String
当您不能使用普通类时,这很有用。例如,当这不起作用时:
// doesn't work
Type type = ArrayList<String>.class;
您仍然可以使用TypeReference
来获得该课程:
// will yield Class<ArrayList<String>>>
Type type = new TypeReference<ArrayList<String>>(){}.getType();
查看source code of TypeReference
(using Jackson 2.8.5)时,您会看到构造函数主体包含以下几行:
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];
有趣的行是第一行和最后一行。让我们仔细看看第一行:
Type superClass = getClass().getGenericSuperclass();
例如,当您使用匿名类创建子类时:
TypeReference<SomeStype> ref = new TypeReference<SomeType>(){};
然后getClass
返回当前的Class
对象(一个匿名类),而getGenericSuperclass()
将返回当前实现扩展的Class
的{{1}}对象class
等于superClass
。
现在,当查看构造函数主体的最后一行时:
Class<TypeReference<?>>
我们知道_type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
是superClass
的{{1}}对象,我们知道它具有通用参数。因此,将其强制转换为Class
。此指定的TypeReference<?>
具有方法ParameterizedType
,该方法返回该类指定的所有通用参数的数组。在我们的例子中,它仅为1。因此Type
将产生第一个元素。在示例中,我们将获得实际指定的类型参数getActualyTypeArguments()
。