RestTemplate获取对象列表 - 为什么要使用ParameterizedTypeReference而不是对象数组?

3

我正在尝试使用Spring RestTemplate获取对象列表。我对为什么要选择ParameterizedTypeReference方法来使用restTemplate获取对象列表感到困惑,而不只是使用Object[] .class。

我已经查看了多个答案,建议使用ParameterizedTypeReference。但是我为什么不能只使用Object[] .class呢?我有哪些限制?

我查看了这个链接(https://dev59.com/8FUL5IYBdhLWcg3wzq2a#49752261),其中说到,我只能在简单情况下使用Object[],在处理复杂的JSON结构时必须使用ParameterizedTypeReference。有人能解释一下在什么情况下我不能使用Object[]方法吗?

ParameterizedTypeReference方法:

ResponseEntity<List<Rating>> responseEntity =
                restTemplate.exchange("http://localhost:8084/ratingsdata/user/" + userId,
                        HttpMethod.GET, null, new ParameterizedTypeReference<List<Rating>>() {
                        });
List<Rating> ratings = responseEntity.getBody();

Object[] 方法:

List<Rating> ratings = Arrays.asList(restTemplate.getForObject("http://localhost:8084/ratingsdata/user/"+userId, Rating[].class));
1个回答

3
答案很简单,为了在运行时保留类型信息。
列表可以充当数组,但数组不能充当列表。你的代码之所以能工作,是因为你将一个数组强制转换为列表,正如已经说明的,列表可以充当数组,所以这次是安全的。
但总的来说,强制转换是不好的做法。
当你进行强制转换时,你正在冒险,你基本上是强迫编译器“相信你”所做的事情。因此,你告诉编译器什么是正确或错误的,而不是编译器告诉你,这是一种风险,有可能会导致程序崩溃。如果你在运行时出错,很难控制,也很难修复。
有很多程序员有很多意见,但只有一个编译器有一个意见,我们应该信任它。
所以回到问题,ParameterizedTypeReference<T>.class实际上是做什么的?
如果你看它的构造函数,你会发现它像一个携带类型信息的容器。通过执行 new ParameterizedTypeReference<List<Foo.class>> {};,你正在实例化一个匿名类并传入一个类型。然后在构造函数中,它从传递的类型提取类型信息并在内部存储它。然后在稍后的时候,我们可以执行 getType() 来获取类型信息,以便我们可以在运行时进行类型安全的“转换”。
    final ParameterizedTypeReference<List<String>> typeRef = new ParameterizedTypeReference<>() {};
    final Type type = typeRef.getType();
    final String typeName = type.getTypeName();
    System.out.println(typeName);
    // will print "java.util.List<java.lang.String>"

这种模式被称为"超级类型标记",你可以在Neal Gafter的博客-超级类型标记中了解更多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接