Подтвердить что ты не робот

Почему Java Collection <E>.toArray() возвращает объект [], а не E []?

До генерирования Java, Collection.toArray() не имел способа узнать, какой тип массива ожидал разработчик (особенно для пустой коллекции). Насколько я понимаю, это было основным аргументом в пользу идиомы collection.toArray(new E[0]).

С generics Collection<E>.toArray() может возвращать массив, полный экземпляров E и/или его специализаций. Интересно, почему тип возврата по-прежнему равен Object[], а не E[]. На мой взгляд, возврат E[] вместо Object[] не должен нарушать существующий код.

Смотрите: Collection.toArray(), Collection.toArray(T[]) и связанная с этим тема java: (String []) List.toArray() предоставляет ClassCastException

4b9b3361

Ответ 1

Это очень хороший вопрос. Ответ заключается в том, что дженерики также называются "стираниями". Это не просто имя. Информация, закодированная дженериками, используется только во время компиляции, а затем удаляется. Таким образом, JVM даже не знает этот общий тип E, поэтому он не может создать массив E[].

Другой метод toArray(T[] a) получает информацию о типе из аргумента во время выполнения. По этой причине прототип этого метода <T> T[] toArray(T[] a): он получает массив типа T и может возвращать массив типа T. Тип передается как параметр.

Ответ 2

"Стирание типа" является лишь частичным объяснением: ни метод Collection, ни его toArray() не имеют никакой информации о E во время выполнения.

Кроме того, из-за обратной совместимости, Collection.toArray() должен возвращать Object[]. До Java 1.5 не было способа узнать общий тип для коллекции, поэтому это был единственный разумный дизайн API.

Ответ 3

@Lukas, относительно: "новый E []"

Новый E [0] поднял ошибку компилятора, как вы, вероятно, ожидали. Обходной путь, который я нашел, это:

final E [] returnArray = (E []) events.toArray(новое событие [events.size()]);

N.B. код находится в классе шаблона Listener < E extends Event > .

В моем обходном пути тип стирания - это и проблема, и решение. Приведение к (E []) безопасно, потому что его точный тип стирается до Event []. Единственный недостаток, который я вижу, - это предупреждение компилятора о "непроверенных или небезопасных операциях" (что, очевидно, в данном случае приведение не выполняется при стирании типа).

@Lukas, относительно обратной совместимости

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

Другими словами, исходный код, который до сих пор ожидал, что Collection.toArray() возвратит Object [], должен с полным удовольствием получить E [].

И что касается байтового кода, Object [] и E [] в любом случае одинаковы из-за стирания типа.