TypeReference <Map <String,String >>(){}

Rai*_*ish 2 java rest web-services jackson

几天前,我开始从事网络服务项目.该项目使用Jackson来编组和解组JSON对象.所以我的问题是:

为什么我总是要把{}我创建的实例放在什么时候TypeReference?我知道构造函数是protected,但为什么protected呢?我认为这就像是一个黑客,可以让构造函数创建一个构造函数的实现,因为它TypeReferenceabstract你可以做到的.但这有什么意义呢?

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>>()
        { //
        });
Run Code Online (Sandbox Code Playgroud)

Lin*_*ica 6

TL; DR

通过子类化,可以TypeReference提取实际的泛型类型参数.例如:

TypeReference<String> ref = new TypeReference<String>(){};
System.out.println(ref.getType());
Run Code Online (Sandbox Code Playgroud)

打印:

class java.lang.String
Run Code Online (Sandbox Code Playgroud)

当您不能使用普通类时,这可能很有用.例如,当这不起作用时:

// doesn't work
Type type = ArrayList<String>.class; 
Run Code Online (Sandbox Code Playgroud)

您仍然可以使用以下方法获得该课程TypeReference:

// will yield Class<ArrayList<String>>>
Type type = new TypeReference<ArrayList<String>>(){}.getType();
Run Code Online (Sandbox Code Playgroud)

详细

查看(使用Jackson 2.8.5)源代码时,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];
Run Code Online (Sandbox Code Playgroud)

有趣的线条是第一个也是最后一个.让我们仔细看看第一行:

Type superClass = getClass().getGenericSuperclass();
Run Code Online (Sandbox Code Playgroud)

例如,当您创建子类时,使用匿名类:

TypeReference<SomeStype> ref = new TypeReference<SomeType>(){};
Run Code Online (Sandbox Code Playgroud)

然后getClass返回当前Class对象(一个匿名类),并将从当前实现中getGenericSuperclass()返回Class对象的class延伸,在我们的例子中,superClass将等于Class<TypeReference<?>>.

现在,当查看构造函数体的最后一行时:

_type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
Run Code Online (Sandbox Code Playgroud)

正如我们知道superClass的是Class对象TypeReference<?>,我们知道它有一个通用的参数.因此演员阵容ParameterizedType.这个指定Type的方法getActualyTypeArguments()返回该类指定的所有泛型参数的数组.在我们的例子中,它只是1.因此[0]将产生第一个元素.在示例中,我们将获得实际指定的类型参数SomeType.