2013-05-19 14 views
9

Per vari motivi voglio convertire una lista in un array, tuttavia la collezione contiene oggetti che sono generici.Come convertire in modo sicuro da una raccolta di tipi generici a un array?

Ho provato le seguenti quattro opzioni per farlo compilare senza bisogno di un'annotazione @supressWarnings ('deselezionata'), ma nessuna funziona. C'è una soluzione per farlo funzionare correttamente, o sono obbligato a usare l'annotazione?

Iterator<T>[] iterators; 
final Collection<Iterator<T>> initIterators = new ArrayList<Iterator<T>>(); 

// Type safety: Unchecked cast from Iterator[] to Iterator<T>[] 
iterators = initIterators.<Iterator<T>>toArray(
     (Iterator<T>[])new Iterator[initIterators.size()]); 

// Type safety: Unchecked invocation toArray(Iterator[]) of the generic 
// method toArray(T[]) of type Collection<Iterator<T>> 
// Type safety: The expression of type Iterator[] needs unchecked conversion 
// to conform to Iterator<T>[] 
iterators = initIterators.<Iterator<T>>toArray(
     new Iterator[initIterators.size()]); 

// Type safety: The expression of type Iterator[] needs unchecked conversion 
// to conform to Iterator<T>[] 
iterators = initIterators.toArray(new Iterator[initIterators.size()]); 

// Doesn't compile 
iterators = initIterators.toArray(new Iterator<T>[initIterators.size()]); 
+0

Forse [[questo] (http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#FAQ104)] aiuterà un po '. Ad ogni modo mi interessa anche perché qualcuno vorrebbe usare gli array (che non supportano i generici) invece di dire ArrayList. – Pshemo

+0

possibile duplicato di [Array of Generic List] (http://stackoverflow.com/questions/7810074/array-of-generic-list). Vedi anche: [Tipi generici in un array per un albero con più di un figlio] (http://stackoverflow.com/questions/15957325/generic-types-in-an-array-for-a-tree-with-more -than-figlio unico). –

+0

@PaulBellora Penso che le domande che elencherai non siano duplicate, sebbene parlino di materiale simile. –

risposta

12

Non c'è modo type-safe per creare una matrice di un tipo parametrico come Iterator<T>[].

In alternativa, è possibile creare un array raw: Iterator<?>[]. Oppure, se è possibile evitare completamente l'utilizzo di array, utilizzare un tipo di raccolta come List<Iterator<T>>.

La ragione per cui non è possibile è che gli array Java sono covarianti ei limiti parametrizzati dei tipi generici sono invarianti. Vale a dire:

Integer[] integers = new Integer[1]; 
Number[] numbers = integers; // OK because Integer extends Number 
numbers[0] = new Double(3.14); // runtime exception 

Il compilatore permette l'assegnazione perché Double estende Number e il tipo dichiarato di numbers è Number[]. Ma in fase di esecuzione l'effettiva istanza dell'oggetto dell'array è l'originale Integer[1] e gli array conoscono il tipo di oggetti che contengono.

Con i generici, i tipi parametrizzati sono diversi. Per uno, a causa della cancellazione del tipo in fase di compilazione , non conoscono intrinsecamente i loro tipi di runtime.

List<Integer> integerList = new ArrayList<Integer>(); 

List<Number> numberList = integerList; // compiler error, prevents: 
numberList.add(new Double(3.14)); // would insert a Double into integerList 

Collection<Integer> integerCollection = integerList; // allowed 
// OK because List extends Collection and the <type parameter> did not change 

Collection<Number> numberCollection = integerList; // compiler error 
// an "Integer" is a "Number" 
// but "a collection of Integers" is more specific than "a collection of Numbers" 
// and cannot be generally treated the same way and guarantee correct behavior 

List<?> rawList = integerList; // allowed, but... 
rawList.add(new Integer(42)); // compiler error, Integer is not a ... a what? 

con i generici, in Java, si fa affidamento sul compilatore (non il runtime) per verificare che i tipi generici siano corretti e sicuri.

Così, mentre un Iterator<?>[] sa in fase di esecuzione che è un array che contiene Iterator elementi, il <T> in Iterator<T>[] è cancellata in fase di compilazione e il runtime non ha modo di sapere quello che doveva essere. Quindi ricevi un avviso non controllato.

+0

+1 Buona spiegazione. –

+0

Buona spiegazione, ma sfortunatamente non mi aiuta. I _have_ a Collection >, ma io _need_ a Iterator []. Voglio convertire il primo in quest'ultimo, e posso farlo, ma non senza un avvertimento del compilatore. È solo questo avvertimento di cui voglio liberarmi. –

+0

@PaulWagland: è impossibile ottenere un valore non '' null' di tipo 'Iterator []' in qualsiasi modo senza sopprimere un'avvertenza da qualche parte (nel codice o in una funzione che si chiama) – newacct

Problemi correlati