【发布时间】:2016-10-27 14:22:57
【问题描述】:
我正在尝试在将 json 反序列化为 pojo 的方法中使用泛型,以便它可以返回任何对象类型。
这是我的代码:
private Bla(List<A> as, List<B> bs)
{
this.as = as;
this.bs = bs;
}
public static Bla from(JsonObject json)
{
return new Bla(Bla.<A>load(json, As), Bla.<B>load(json, Bs));
}
private static <T> List<T> load(JsonObject jsonObject, String param)
{
return jsonObject.getJsonArray(param).stream()
.map(Bla::getItem)
.collect(Collectors.toList());
}
private static <T> T getItem(Object json)
{
try {
return mapper.readValue(json.toString(), new TypeReference<T>() {
});
} catch (IOException e) {
throw new RuntimeException("Error parsing json items", e);
}
}
问题是.collect(Collectors.toList());似乎没有编译导致无法解析实例类型。
编译错误是:
错误:(43、25)java:不兼容的类型:推理变量 T 具有不兼容的边界 等式约束:T 下界:java.lang.Object为了避免在我的示例中混淆 A 和 B 是 Pojos
问候。
【问题讨论】:
-
这对于类型推断来说可能太多了,因为您需要将
T从collect传播回map。试试map(x -> Bla.<T>getItem(x))。另一种选择是在现有的map之后添加第二个map(x -> (T) x)。 -
并不是说这段代码无论如何都行不通。在你实例化的地方,
new TypeReference<T>() {},没有人知道T实际上是什么。甚至它的调用者load也不知道A或B。 -
@Marko Topolnik:它会编译,因为
T是可具体化的要求不能表达为TypeReference。它会在运行时失败。 -
@Marko Topolnik:不,从编译器的角度来看,它不需要是可具体化的类型,只要可以证明正确性即可,这对于实际上不使用的类来说很容易
T。在运行时检查T的尝试对此处的编译器不可见。那么它将是TypeVariable,Json 映射器希望在其中获得Class... -
@Tunaki :
Bla不必是使此代码正确的泛型类型。如果Bla是非泛型类型,那么从泛型类型系统的角度来看,代码是正确的。然而,由于类型擦除,在运行时根据需要创建A或B实例的愿望将无法实现。