Почему, когда я пытаюсь создать массив ArrayLists: ArrayList<Integer>[] arr=new ArrayList<Integer>[40];
возникает ошибка, а java не позволяет этого?
Есть ли какая-то причина, связанная с реализацией обобщений, обобщений на любом языке или чего-то другого в Java?
java
language-design
generics
Якоб Вейсблат
источник
источник
Ответы:
Это одна из основных дыр в дженериках Java, массивы ковариантны , это означает, что массив типа
Foo[]
является подклассомObject[]
иParentOfFoo[]
. Сравните это с тем,List<Foo>
что не имеет такого поведения.Это было важно, когда в Java не было обобщений (до Java 5), потому что в противном случае нечто вроде универсальной функции сортировки было просто невозможно.
Однако у него есть хитрая проблема, которая позволяет массивам знать, какой у них тип во время выполнения . Однако дженерики в Java основаны на стирании типов. Эти две вещи не очень хорошо сочетаются друг с другом, и именно здесь мы получаем нашу проблему.
Таким образом, в Java 1 ковариантные массивы частично заполняют дыру, которую создает недостаток генериков. Однако когда они пытались правильно заполнить эту дыру, обратная совместимость означала, что массивы было практически невозможно реализовать.
Фактически, парень, который фактически создал основу для дженериков, Мартин Одерский, говорил об этом здесь во время интервью о том, почему он сделал Scala. (Довольно увлекательно, если вам вообще интересна история Scala)
источник
На самом деле, это несколько произвольно.
Проблема в том, что он допускает дыру в системе типов, так как
ArrayList<T>[]
может быть приведен к,Object[]
а затем вы можете поместитьArrayList<U>
в массив, гдеU != T
.Java-дизайнеры решили заблокировать эту дыру как можно охотнее, вообще не допуская
new ArrayList<T>[N]
.Тем не менее, он также мог быть отключен, если не разрешать передачу массивов универсальных шаблонов (без предупреждения «unchecked»).
источник
Integer
в этоObject[]
на самом делеString[]
потому что массив является ковариантным, каждый тип которого является подклассом объекта, так что это дает ошибку во время выполнения из-за исключения приведения. в то время как универсальный тип является инвариантным, поэтому, когда он основывается на типе обеспечить или типобезопасен, поэтому, если тип не такой, как он, создает тип, он дает ошибку компилятора.
источник