Почему java-генерики не могут быть в массивах?

10

Почему, когда я пытаюсь создать массив ArrayLists: ArrayList<Integer>[] arr=new ArrayList<Integer>[40];возникает ошибка, а java не позволяет этого?

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

Якоб Вейсблат
источник

Ответы:

20

Это одна из основных дыр в дженериках Java, массивы ковариантны , это означает, что массив типа Foo[]является подклассом Object[]и ParentOfFoo[]. Сравните это с тем, List<Foo>что не имеет такого поведения.

Это было важно, когда в Java не было обобщений (до Java 5), ​​потому что в противном случае нечто вроде универсальной функции сортировки было просто невозможно.

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

Таким образом, в Java 1 ковариантные массивы частично заполняют дыру, которую создает недостаток генериков. Однако когда они пытались правильно заполнить эту дыру, обратная совместимость означала, что массивы было практически невозможно реализовать.

Фактически, парень, который фактически создал основу для дженериков, Мартин Одерский, говорил об этом здесь во время интервью о том, почему он сделал Scala. (Довольно увлекательно, если вам вообще интересна история Scala)

Даниэль Гратцер
источник
3

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

На самом деле, это несколько произвольно.

Проблема в том, что он допускает дыру в системе типов, так как ArrayList<T>[]может быть приведен к, Object[]а затем вы можете поместить ArrayList<U>в массив, где U != T.

Java-дизайнеры решили заблокировать эту дыру как можно охотнее, вообще не допуская new ArrayList<T>[N].

Тем не менее, он также мог быть отключен, если не разрешать передачу массивов универсальных шаблонов (без предупреждения «unchecked»).

DepressedDaniel
источник
Этот ответ недооценен. Очень просто и не использует жаргон на неопределенных терминах. Огромное спасибо.
Тунг Нгуен,
Возможно, вы захотите уточнить, почему это не так, как в случае, когда вы помещаете Integerв это Object[]на самом делеString[]
Caleth
-3

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

Нулевой код
источник