Дженерики Java и инициализация массива

Какое объяснение для следующего:

public class GenericsTest {
    //statement 1
    public ArrayList<Integer>[] lists;

    public GenericsTest()
    {
            //statement 2
        lists = new ArrayList<Integer>[4];
    }
}

Компилятор принимает оператор 1. Оператор 2 помечается компилятором как «создание универсального массива».

Хорошее объяснение, которое я видел относительно запрета универсальных массивов, - это Вот этот, утверждающее, что, поскольку массивы ковариантны, а универсальные - нет, вы можете подорвать общую типизацию, если вы разрешите универсальные массивы.

Оставляя в стороне споры о том, должен ли язык идти на крайние меры, создавая такого рода сложную несогласованность в обращении с дженериками, чтобы вы не застрелились, как бы вы ни старались (и если кто-нибудь знает о каких-либо хороших дискуссиях по поводу родственников). достоинства / недостатки проблемы, пожалуйста, опубликуйте, мне было бы интересно увидеть аргументы), почему оператор (1) должен быть разрешен, если (2) нет?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
18
0
5 738
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Это потому, что вы не можете создавать, но вы можете использовать их:

public class GenericsTest {
    //statement 1
    public ArrayList<Integer>[] lists;

    public GenericsTest()
    {
        //statement 2
        lists = new ArrayList[4];
        //statement 3
        lists[0].add(new Integer(0));
        //statement 4
        lists[0].add(new String(""));
    }
}

Утверждение 3 возможно, утверждение 4 приведет к ошибке компилятора.

Оператор 4 действительно дает ошибку, но оператор 2 дает предупреждение о «неконтролируемом преобразовании», чего оно стоит.

nsayer 22.01.2009 23:56

На самом деле, я думаю, что поведение оператора 3 было бы неопределенным, поскольку вы не выполнили «lists [0] = new ArrayList <Integer> ();» первый...

Evan 23.01.2009 02:47

Хм, хороший крик. Пример действительно компилируется (если вы не укажете оператор 4), но я его не запускал. Заявление 3 тогда приведет к исключению RuntimeException.

Sven Lilienthal 23.01.2009 11:17
Ответ принят как подходящий

Кажется, есть неясные случаи, когда вы могли непреднамеренно вызвать ClassCastException, как описано здесь http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf (раздел 7.3)

интересное обсуждение этой темы можно найти здесь http://courses.csail.mit.edu/6.170/old-www/2006-Spring/forum/index.php%3Ftopic=324.msg1131.html

Хорошие рекомендации, спасибо. Думаю, придется пройти через все это еще немного.

Steve B. 22.01.2009 22:50

В этом случае я бы не стал использовать массивы именно по этой причине. Объявление "списков" в исходном коде могло быть

List<List<Integer>> lists = new ArrayList<List<Integer>>(4);
for(int i = 0; i < 4; i++) lists.add(null); // or add an empty ArrayList<Integer>

(вы должны использовать интерфейс, а не реализацию в объявлениях переменных)

Вместо синтаксиса array [] вы должны использовать get () или set (). В остальном это эквивалент.

Итак, актуальный вопрос: почему нет ошибки при объявлении универсального массива? ?

Вы всегда будете получать ошибку, если сделаете что-то ошибочное. Добавление ошибки там, где технически проблемы нет, просто добавляет беспорядка (хотя редактор может захотеть указать вам на это).

В некоторых случаях вы можете захотеть немного изменить правила, не проверяя приведение. Нет необходимости заставлять код быть заваленным большим количеством подавлений предупреждений, чем необходимо (кроме как указать на глупость).

Другие вопросы по теме