Java generics: Что такое проблема с компилятором? ( "нет уникального максимального экземпляра" )

У меня есть следующие методы:

public <T> T fromJson( Reader jsonData, Class<T> clazz ) {
    return fromJson( jsonData, (Type)clazz );
}

public <T> T fromJson( Reader jsonData, Type clazz ) {
    ...
}

Компилятор говорит о первом методе:

 type parameters of <T>T cannot be determined;
 no unique maximal instance exists for type variable T
 with upper bounds T,java.lang.Object

 return fromJson( jsonData, (Type)clazz );
                ^

В чем проблема?

Ответ 1

Проблема заключается в определении второго метода:

public <T> T fromJson( Reader jsonData, Type clazz ) {

Компилятор не может сказать, какой тип T может иметь. Вы должны вернуть Object здесь, потому что вы не можете использовать Type<T> clazz (Type не поддерживает генерики).

Это приводит к литой (T) в первом методе, которая вызовет предупреждение. Чтобы избавиться от этого предупреждения, у вас есть два варианта:

  • Сообщите компилятору тип. Используйте этот (нечетный) синтаксис:

    this.<T>fromJson( jsonData, (Type)clazz );
    

    Обратите внимание, что здесь нужен this, потому что только <T>fromJson() является незаконным синтаксисом.

  • Используйте аннотацию @SuppressWarnings("unchecked").

Ответ 2

Я столкнулся с той же проблемой и обнаружил, что это ошибка (# 6302954) в JDK. Он был исправлен в jdk 6u25.

Я работал над одним из экземпляров этой проблемы, но решил обновить версию JDK в поле CI.

Ответ 3

Это похоже на провал вывода. Первый метод явно намеревается вызвать второй метод с аргументом типа, являющимся тем же самым параметром T, который он имеет. Но, вероятно, компилятор не может понять, потому что его система вывода недостаточно хороша.

В любом случае вы должны иметь возможность явно указывать аргумент типа и он должен избавиться от ошибки:

public <T> T fromJson( Reader jsonData, Class<T> clazz ) {
    return this.<T>fromJson( jsonData, (Type)clazz );
}

Ответ 4

У меня тоже была аналогичная проблема при компиляции в NetBeans. Все, что мне нужно было сделать, это изменить версию JDK с 16 до 32 бит в настройках > Компилировать > Java-платформу.