使用Generic类型收集流

时间:2016-10-27 14:22:58

标签: java java-8

我试图在一个方法中使用泛型,我将json反序列化为pojo,因此它可以返回任何对象类型。

这是我的代码:

$documents = $collectionHandler->all($collectionId);

var_dump($documents);

问题是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); } } 似乎不是编译原因无法解析实例类型。

编译错误是:

Error:(43, 25) java: incompatible types: inference variable T has incompatible bounds
        equality constraints: T
        lower bounds: java.lang.Object

为避免混淆我的例子A和B是Pojos

问候。

1 个答案:

答案 0 :(得分:8)

让我们来看看这个方法:

private static <T> List<T> load(JsonObject jsonObject, String param)
{
    return jsonObject.getJsonArray(param).stream()
                                         .map(Bla::getItem)
                                         .collect(Collectors.toList());
}

最后一步的类型Collectors.toList()必须为List<T>,但要获得上一步的类型,Bla::getItem必须推断为T getItem。由于getItem是一种通用方法,因此需要一种类型约束传播的复杂模式,这显然比Java的类型推断所能处理的更多。要解决此问题,请使用提示帮助编译器:

.map(Bla::<T>getItem)

(此语法变体的功能归功于用户NándorElődFekete)。

第二个问题是您的getItem方法:

private static <T> T getItem(Object json)
{
    return mapper.readValue(json.toString(), new TypeReference<T>() {};
}

这里使用TypeReference没有用,因为T不是具体类型。它将在编译器在此创建的匿名类中保持不确定状态,因此Jackson将不会从中获得任何有用的提示。您可以使用更简单的readValue签名,但不会使用TypeReference