2010-10-18 11 views
9

Ho chiamato un metodo getElements che restituisce Iterable<Element>."Iterable <Element> non può essere trasmesso a Elenco <Element>" - Non è `Elenco` un tipo di` Iterable`?

ho fatto questo:

List<Element> elements = (List<Element>) getElements(); 

Questo genera l'errore:

java.lang.ClassCastException: com.utesy.Element$3 
cannot be cast to java.util.List 

ho pensato un List era un tipo di Iterable?

+1

pubblicare il codice di 'getElements();' metodo –

+1

L'interfaccia 'list' estende l'interfaccia' Iterable' - quindi sì, 'list' è di tipo "Iterable", come dici tu. Ma ciò non significa che qualunque cosa 'Iterable' sia restituita da' getElements' è anche un 'Elenco'. Tutte le liste sono iterabili, ma non tutti gli iterabili sono elenchi. –

risposta

24

Sì, List<T> estende Iterable<T>, ma questo non significa che si può trasmettere da qualsiasiIterable<T> a List<T> - solo quando il valore in realtà si riferisce a un'istanza di un tipo di List<T>. È completamente possibile implementare Iterable<T> senza implementare il resto dell'interfaccia List<T> ... in tal caso, cosa ti aspetti che accada?

Per dirla in termini più semplici, cambiamo lo Iterable<T> in Object e List<T> in String. String estende Object, in modo da poter provare di trasmettere da Object a String ... ma il cast riuscirà solo in fase di esecuzione se il riferimento effettivamente riferisce ad un String (o è nullo).

0

Non tutte le Iterable s sono List s, quindi non è sicuro per lanciare un arbitrario Iterable ad un List.

prendere qualsiasi Set per esempio, un HashSet è Iterable ma gli elementi senza fine, quindi non si può implementare l'interfaccia List, e non è quindi un List.

+2

'' "ma gli elementi non hanno ordine, quindi non è un' Elenco' "- non è questo il motivo per cui un' HashSet' non è un 'Elenco'. Un 'HashSet' non è un' Elenco' perché non implementa l'interfaccia 'Lista'. '' –

+0

@Matt Ball, vero ... riformulato un po '... meglio? :) – aioobe

0

Da messaggio di eccezione è chiaro che Iterable<Element>non è calcinabile perList<Element>

quindi è necessario tornare List<Element> da getElements()

1

List è un subinterface di Iterable significato Tale elenco comprende praticamente tutto ciò che Iterable ha, tuttavia, non il contrario. Quindi non tutti i metodi in un'istanza di List avranno un equivalente in Iterable.

Cerca di evitare questo tipo di casting.

ti consiglierei di dare un'occhiata veloce al Java 6 API e i tutorial che coprono scacciando

17

List<Element> è un tipo di Iterable<Element>, ma questo non significa che tutti gli oggetti sono Iterable<Element>List<Element> oggetti. Puoi trasmettere un List<Element> come Iterable<Element>, ma non viceversa.

Una mela è un tipo di frutta, ma ciò non significa che tutti i frutti siano mele. Puoi lanciare una mela come frutto, ma non viceversa.

+13

+1 per non avere 229k rep – willcodejavaforfood

0

Elenco implementa l'interfaccia Iterable ma ciò non significa che Iterable può essere restituito a List. Iterable è molto più generale e potrebbe essere Hash o un tipo esotico che non ha alcuna relazione con List. (Sembra che getElements() restituisca un'istanza di qualche classe interna anonima contenuta insieme a getElements all'interno della sua classe).

Se getElements dovesse contenere Liste, questo sarebbe un cast valido. Poiché il tipo restituito da getElements() non era in realtà un elenco, ciò genera un errore di runtime.

+0

Elenca le implementazioni Iterable e questo * fa * significa che può essere lanciato su di esso. Il problema che l'OP sta avendo sta andando nella direzione opposta. Questo non ha nulla a che fare con il suo essere uno strumento vs estendere. –

+0

Mi dispiace, il "non significa che possa essere lanciato" non è chiaro, ho inserito "it" in modo che non possa essere interpretato erroneamente come tu hai. – AshirusNW

24

È possibile trasformare Iterable in un elenco con

List<Element> elements = Lists.newArrayList(getElements()); 
+13

... dove Liste è com.google.common.collect.Lists. – jarnoan

+0

Questo è il modo più conciso per farlo. Altrimenti avrete bisogno di una lunga implementazione :-(- o usate semplicemente Scala;) –

4

perché no:

Iterable<Element> i = ...; //is what you have 
    List<Element> myList = new LinkedList<Element>(); 
    for (Element e:i) { 
     myList.add(e); 
    } 

? non ha bisogno di Google Lib.

+0

modo più semplice finora ... –

0

si può provare a mettere una guardia con instanceof:

if (AnElement instanceof AList){ 
    //cast 
    AList = (AnList)Element 
} 
Problemi correlati