TL;DR
通过子类化,可以TypeReference
来提取actual泛型类型参数。例如:
TypeReference<String> ref = new TypeReference<String>(){};
System.out.println(ref.getType());
Prints:
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();
Detailed
当看着的源代码TypeReference(使用杰克逊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>(){};
Then getClass
返回当前的Class
对象(匿名类),以及getGenericSuperclass()
将返回Class
对象从class
在我们的例子中,当前的实现延伸自superClass
将等于Class<TypeReference<?>>
.
现在查看构造函数主体的最后一行:
_type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
据我们所知,superClass
is the Class
对象为TypeReference<?>
我们知道它有一个通用参数。因此演员阵容ParameterizedType
。这指定了Type
有方法getActualyTypeArguments()
它返回该类指定的所有通用参数的数组。在我们的例子中它只是 1。所以[0]
将产生第一个元素。在示例中我们将获取实际指定的类型参数SomeType
.