使用Generic类型收集流

pau*_*aul 11 java java-8

我试图在一个方法中使用泛型,我将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);
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是.collect(Collectors.toList());似乎没有编译原因无法解析实例类型.

编译错误是:

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

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

问候.

Mar*_*nik 8

我们来看看这个方法:

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

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

.map(Bla::<T>getItem)
Run Code Online (Sandbox Code Playgroud)

(这个句法变体的功劳归于用户NándorElődFekete).

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

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

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