Странная проблема дженериков - PullRequest
5 голосов
/ 28 июня 2010

Кто-нибудь знает, почему следующий код не компилируется, и во время компиляции я получаю исключение несовместимых типов?

public class Test<T> {

public static void main(String[] args)
{
    // using Test<?> solves the compilation error
    Test test = new Test();

    // getting error incompatible types:
    // found   : java.lang.Object
    // required: java.lang.Integer
    Integer number = test.getDays().get(0);
}


private List<Integer> getDays() {
    return new ArrayList<Integer>();
}

}

и почему использование Test с неограниченным подстановочным знаком решает эту проблему? Я использую Java версии 1.6.0_12

Ответы [ 6 ]

8 голосов
/ 28 июня 2010

Я интерпретирую вопрос как , почему test.getDays() не возвращает List<Integer>, когда тип возвращаемого значения не зависит от параметра типа, T?

Когда высоздайте переменную, которая является необработанной ссылкой на экземпляр Test, компилятор отбрасывает все обобщенные элементы для доступа через эту переменную (для обратной совместимости).

Поскольку test не имеет своего типа <T>указанное также означает, что <Integer> для getDays отбрасывается.

3 голосов
/ 28 июня 2010

Небольшое отличие от ответа Адель, но вы имели в виду это?

public class Test<T> {

public static void main(String[] args)
{
    Test<Integer> test = new Test<Integer>();

    Integer number = test.getDays().get(0);
}


private List<T> getDays() {
    return new ArrayList<T>();
}

} 
1 голос
/ 28 июня 2010

Я попытался скомпилировать его, и у меня возникли те же проблемы.Я не думаю, что ОП хочет объяснить, как использовать дженерики.Попробуйте сами ... странным является то, что он "должен" работать, потому что универсальный тип T вообще не используется, поскольку объявление getDate заявляет, что оно возвратит ссылку на список целых чисел.

Вы можете создать экземпляр теста следующим образом:

Test<JFrame> test = new Test();

... и он скомпилируется!(конечно, вы можете использовать любой существующий тип здесь ...) Странная вещь ...

Если вы удалите обобщенное объявление, оно также работает (конечно).

1 голос
/ 28 июня 2010

Попробуйте это:

public class Test<T> {

public static void main(String[] args)
{
    // using Test<?> solves the compilation error
    Test<Integer> test = new Test<Integer>();

    // getting error incompatible types:
    // found   : java.lang.Object
    // required: java.lang.Integer
    Integer number = test.getDays().get(0);
}


private List<Integer> getDays() {
    return new ArrayList<Integer>();
}

} 
0 голосов
/ 28 июня 2010

Когда вы объявляете переменную или поле как необработанный тип, все виды использования этого поля или переменной теряют всю общую информацию, а не только общую информацию, связанную с переменной типа, отброшенной необработанным типом. Это означает, что ваш вызов test.getDays() вернул List, а не List<Integer>, хотя Integer не имеет отношения к T.

0 голосов
/ 28 июня 2010

Компилятор не может определить фактический тип для Test, поскольку вы указали его как универсальный, а затем использовали необработанный тип.Добавление?подстановочный знак информирует компилятор о том, что фактический класс может быть определен только во время выполнения;он не будет проверять тип класса.

Вы также можете решить задачу компиляции, сделав класс Test не универсальным или заставив getDays () вернуть List.

...