2013-02-23 2 views
2

Почему Collection<E>.toArray() (непараметризированный метод) return Object[]?Почему коллекция <E> #toArray() не возвращается E []?

Является ли это одним из тех сознательно принятых решений? Есть ли причина, почему метод toArray() не смог бы вернуть E[], если бы захотел?

+0

тип стирание - причина. java не знает, что T во время выполнения, поэтому он не может создать массив соответствующего типа. Другой, «типичный» вариант toArray требует массива «prototype» с правильным типом (который фиксируется во время компиляции!), Который он может копировать. – Pyranja

+0

Это исторический. Метод предшествует дженерикам и хранится в его существующей форме, чтобы не нарушать устаревший код. – Perception

+0

Я не уверен в этом. Я не вижу способа получить класс 'E' в этом методе. –

ответ

6

Это потому, что массив типа T не может быть создан без знания типа Class<T>. Сравните это с toArray(T[] array), который имеет следующий источник (пример от LinkedList). Обратите внимание, что полученный массив используется не только как возможный контейнер, но и, возможно, создает экземпляр нового массива этого типа. Этот код генерирует исключение, если T не является суперклассом E; если объекты не могут быть добавлены в массив.

@SuppressWarnings("unchecked") 
public <T> T[] toArray(T[] a) { 
    if (a.length < size) 
     a = (T[])java.lang.reflect.Array.newInstance(
          a.getClass().getComponentType(), size); 
    int i = 0; 
    Object[] result = a; 
    for (Node<E> x = first; x != null; x = x.next) 
     result[i++] = x.item; 

    if (a.length > size) 
     a[size] = null; 

    return a; 
} 
1

Дженерики на Java реализованы с использованием техники, называемой стиранием стилей. Это означает, что экземпляр родового класса не имеет никакой информации о его родовом типе. Рассмотрим

List<String> list = new ArrayList<String>(); 
list.toArray(); 

поскольку список не знает о его общего типа он может создать только Object []

0

Массив контейнеров ассоциированный тип данных элемент, сохранившийся во время выполнения. Если вы создаете массив объектов, а затем добавить строки, этот объект не будет колдовать к String []:

Object[] objArr = new Object[] {"a", "b"}; 
    String[] strArr = (String[]) objArr; //Produces ClassCastException 

Вы также можете заметить, как это свойство используется массив во время выполнения, когда вы добавляете товар несоответствующего типа в массив:

String[] strArr = new String[] {"a", "b"}; 
    Object[] objArr = (Object[]) strArr; //Legal this time 
    objArr[0] = 15; //Produces ArrayStoreException 

аргументы родового типа стираются во время выполнения, поэтому JVM не знает, что конкретный тип массива для создания во время выполнения при вызове ToArray().

Смежные вопросы