Массив параметризованных типов

Мне трудно понять, какой тип параметра ожидается в RHS следующих

ArrayList<Pair<ParseNode,ParseNode>>[] nodes = new ArrayList[indexes.length];

Почему копия <Pair<ParseNode,ParseNode>> не является законной?

Ответы

Ответ 1

Массивы конкретных параметризованных типов по своей сути нарушаются. Помните, что массивы ковариантны, а проверка типа массива - это операция выполнения. Во время выполнения все дженерики стираются, поэтому проверка хранилища массивов не может определить <Pair<ParseNode, ParseNode>> из <Pair<BigInteger,IOException>>.

Фундаментальным договором общего является "Я, компилятор, обещаю, что если вы пишете код, который не генерирует никаких предупреждений, вы никогда не получите исключение класса при выполнении во время выполнения".

Также компилятор не гарантирует вам, что он сможет дать вам ошибку времени компиляции, если в этот массив помещено что-то, что не является ArrayList<Pair<ParseNode,ParseNode>>. Кроме того, система времени выполнения не гарантирует, что вы получите исключение ArrayStoreException (например, спецификация языка), если вы добавите неправильный тип, а не ClassCastException позже, когда вы его отпустите. (Вторая часть действительно, почему это фактически незаконное, а не просто предупреждение, это приведет к массиву, который не подчиняется спецификации языка.)

Поэтому он не позволяет вам объявлять их таким образом и заставляет вас признать "небезопасное" предупреждение. Таким образом, он сказал: "Я сказал вам, что не могу гарантировать, что в результате использования этого массива не будет исключений для исключения классов", - сказал он вам, чтобы убедиться, что вы здесь только здесь. "

Ответ 2

Java не поддерживает общие массивы. Массивы ковариантны, дженериков нет. Это означает, что если класс A расширяет класс B, то A [] также является B []. И код

A[] a = new A[10];
B[] b = a;

является законным.

Но это не то же самое для дженериков. Вы не можете назначить Foo<T> на Foo<X>, даже если T расширяет X. И поэтому элементы Foo<T>[] не могут быть гарантированы безопасным типом.

ИЗМЕНИТЬ Извините меня за просто ссылку, но я нашел Теория и практика Java: статья Generics gotchas, которая объясняет все, что касается ковариации массивов, лучше, чем я даже будет мечтать.

Ответ 3

Не используйте массив. Используйте другой ArrayList.

ArrayList<List<Pair<ParseNode,ParseNode>>> listOfLists = new ArrayList<List<Pair<ParseNode,ParseNode>>>();

listOfLists.add(new ArrayList<<Pair<ParseNode,ParseNode>>());