2012-05-08 13 views
13

Sto scrivendo un programma con un sacco di enumerazioni e devo restituire molto il set di chiavi di un EnumMap. Ma EnumMap.keySet() restituisce un Set(), così al fine di ottenere il EnumSet che voglio, devo usare un cast:Perché EnumMap <T> .keySet() restituisce un Set <T>() e non un EnumSet <T>()?

EnumMap<SomeEnum, Object> myMap = getMap(); 
EnumSet<SomeEnum> myEnum = (EnumSet<SomeEnum>) myMap.keySet(); 

Se non espressi, il compilatore si lamenta di un tipo non corrispondente; non può convertire da Set<SomeEnum> a EnumSet<SomeEnum>. Sembra inutile doverlo lanciare, poiché le chiavi di un EnumMap saranno sempre un'enumerazione. Qualcuno sa perché il metodo keySet() è stato costruito in questo modo? Ho pensato che a volte potrebbe avere qualcosa a che fare con EnumSet essendo una classe astratta, ma sicuramente EnumMap potrebbe semplicemente restituire qualunque sia il metodo factory di EnumSet.

Cheers, tutto!

MODIFICA: Mi dispiace, il codice sopra riportato genera CastClassException. È possibile ottenere l'EnumSet utilizzando

EnumSet<SomeEnum> myEnum = EnumSet.copyOf(myMap.keySet()); 

Avrei dovuto controllare prima di postare.

+5

Si ottiene un 'Set '. Quale sarebbe il guadagno per avere un 'EnumSet '? –

+0

@PaulBellora Hai ragione, quanto sopra è sbagliato. Lo correggerò. Dovrebbe essere 'EnumSet myEnum = EnumSet.copyOf (myMap.keySet());' – jalopezp

+0

Anche qui è una bella vista della fonte, con javadoc in linea incorporato: http://grepcode.com/file/repository.grepcode.com /java/root/jdk/openjdk/6-b14/java/util/EnumMap.java#EnumMap.keySet%28%29 –

risposta

8

Penso che sia perché lo keySet non è un EnumSet. ;)

Il motivo non è che il keySet è una vista sulla mappa sottostante.

myMap.keySet().removeAll(keysToRemove); // removes multiple keys. 
+0

Ma in ogni caso, quale sarebbe il punto? –

+0

Concettualmente the keySet() è un insieme di enum o un enum set. Se l'API fosse stata progettata diversamente avremmo potuto disporre di un'interfaccia EnumSet ma dato che questo sarebbe uguale a Set, non c'è alcun vantaggio pratico.Se EnumSet potrebbe darti metadati specifici di Enum come il suo tipo di elemento in fase di esecuzione, forse potrebbe fare la differenza. –

0

Se si va alla fonte di quella classe allora si capirà meglio lo scenerio il motivo per cui sta tornando Set. Si può scoprire che al di sotto url

http://www.docjar.com/html/api/java/util/EnumMap.java.html

Spero che questo ti può aiutare.

Divertiti!

+0

È davvero fantastico, non sapevo di poter vedere la fonte per questo! Ho sempre avuto a che fare con l'API. Ma sì, vedo che il metodo keySet() restituisce il Set keySet, che è definito nella superclasse, quindi non potrei averlo in nessun altro modo. Grazie mille, mi divertirò! – jalopezp

+0

@jalopezp Grazie amico –

+3

Dove nelle 800 righe di codice del tuo collegamento mi aspetterei di trovare la risposta alla domanda? Si prega di inviare un estratto della parte pertinente. – Gabe

3

EnumSet è un'implementazione di Set che avviene utilizzando un enum per rappresentare lo spazio chiave. La classe EnumSet non fornisce ulteriori metodi non statici, quindi non ci sarebbe alcun motivo per restituire un EnumSet su un semplice Set.

+0

La migliore risposta finora e l'IMHO semplice . Non riferendosi a dettagli di implementazione/non rilevanti per la progettazione di API) o ipotesi errata che java non abbia tipi di ritorno covarianti (le sottoclassi possono restituire sottoclassi del valore di ritorno nei metodi sovrascritti). –

+0

+1 È meglio guardare effettivamente il design dell'API rispetto al codice sottostante. –

2

Modifica: ho sbagliato, per favore ignora.

EnumMap estende AbstractMap, che dichiara keySet. AbstractMap non può dichiarare che keySet restituisce EnumSet, poiché ciò non è vero per altre sottoclassi di AbstractMap. Quindi, il suo tipo di ritorno è impostato.

+3

Beh, questo non è vero, le sotto classi possono avere valori di ritorno più specifici. Tipi di ritorno covarianti da java 5. –

Problemi correlati