Почему Java * Collection <E>.toArray () возвращает объект [], а не E []? - PullRequest
20 голосов
/ 30 мая 2011

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

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

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

Ответы [ 3 ]

9 голосов
/ 30 мая 2011

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

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

5 голосов
/ 30 мая 2011

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

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

1 голос
/ 30 мая 2011

@ Лукас, относительно: «new E []»

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

final E [] returnArray = (E []) events.toArray (new Event [events.size ()]);

NB код находится в шаблоне класса Listener.

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

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

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

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

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

...