Поскольку ObjectMapper :: convertValue является поддельным в том, как были объявлены обобщения:
public <T> T convertValue(Object fromValue, TypeReference<?> toValueTypeRef)
throws IllegalArgumentException
public <T> T convertValue(Object fromValue, JavaType toValueType)
throws IllegalArgumentException
Нет никакого отношения между T
и TypeReference<?>
: компилятор выводит реальный тип T
, используя контекст, и поскольку контекст:
List<Tractor> tractorList = new ObjectMapper().convertValue(potatoList, new TypeReference<List<Potato>>() {});
Он пытается вывести тип T
: List<Tractor>
совпадения и TypeReference<List<Potato>>
совпадения TypeReference<?>
: TypeReference
может быть совершенно не связан с типом вывода, поэтому он смог создать список Potato
. И так как тип стирается, это возможно в виртуальной машине.
Кажется, то же самое применимо к методу, использующему JavaType
.
Другое использование Class<T>
не будет применяться в вашем случае в вашем случае, потому что вы не можете сделать List<Tractor>.class
.
[править] Если вы хотите воспроизвести подобные проблемы, вы можете сделать это:
List<Potato> potatoes = asList(new Potato());
List<Tractor> tractors = badStuff(potatoes);
private static <T> T badStuff(Object value) {
return (T) value; // should raise a warning due to the cast
}
T
выводится из контекста, и в этом контексте это будет List<Tractor>
. Некоторый компилятор может подавиться этим (Javac может принять это, а Eclipse Compiler - нет и наоборот) и потребовать уточнения типа:
List<Tractor> tractors = MyType.<List<Tractor>>badStuff(potatoes);
Если вы хотите посмотреть более подробно, это, вероятно, поможет: вывод типа .