I´m trying to use generic in a method where I deserializing a json into pojo so it could return whatever object type.
Here my code:
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);
}
}
The problem is that .collect(Collectors.toList());
seems not compile cause cannot resolve the instance type.
The compilation error is:
Error:(43, 25) java: incompatible types: inference variable T has incompatible bounds equality constraints: T lower bounds: java.lang.Object
To avoid confusion in my example A and B are Pojos
Regards.
Let's examine this method:
private static <T> List<T> load(JsonObject jsonObject, String param)
{
return jsonObject.getJsonArray(param).stream()
.map(Bla::getItem)
.collect(Collectors.toList());
}
The type of the last step, Collectors.toList()
must be List<T>
, but to get it the type of the previous step, Bla::getItem
must be inferred as T getItem
. Since getItem
is a generic method, this needs a complex pattern of type constraint propagation which is apparently more than Java's type inference will handle. To solve this, help the compiler with a hint:
.map(Bla::<T>getItem)
(credit for this syntactic variant goes to user Nándor Előd Fekete).
A second issue is your getItem
method:
private static <T> T getItem(Object json)
{
return mapper.readValue(json.toString(), new TypeReference<T>() {};
}
Using TypeReference
here doesn't help because T
is not a concrete type. It will remain non-reified in the anonymous class that the compiler creates here, therefore Jackson will get no helpful hint from it. You can just use a simpler readValue
signature that doesn't take the TypeReference
.