2014-07-05 9 views
11

Errore:Java: impossibile utilizzare EnumSet all'interno di un Enumeration: errore di inizializzazione: Tech Research Talent Albero esempio

... 
Caused by: java.lang.ExceptionInInitializerError 
... 
Caused by: java.lang.ClassCastException: 
class com.evopulse.ds2150.TechTrees$BuildingTechTree 
not an enum 
at java.util.EnumSet.noneOf(Unknown Source) 
at java.util.EnumSet.of(Unknown Source) 
at com.evopulse.ds2150.TechTrees$BuildingTechTree.<clinit>(TechTrees.java:38) 

Ecco un frammento della mia enumerazione

public enum BuildingTechTree { 
//Name      SoftName     Requirements  
NONE      ("NULL",     null), 

-> Questa riga successiva è dove si blocca

BARRACKS     ("Barracks",    EnumSet.of(NONE), 
WALLS_SANDBAGS    ("Sandbag wall",   EnumSet.of(NONE), 

POWERPLANT     ("Power plant",    EnumSet.of(BARRACKS)), 
GUARDTOWER     ("Guard Tower",    EnumSet.of(BARRACKS)); 

Sostituzione EnumSet.of (NESSUNO) e EnumSet.of (BARRACKS) con null, immobili in lavoro di itialization, ma rompe il mio codice, a causa della struttura dei dati mancante ... ovviamente, ma l'ho fatto per testare il resto del mio codice non era in qualche modo la causa.

Rimozione di EnumSet.of (NONE) e sostituzione con solo NONE, e lo stesso per BARRACKS, e modifica di tutte le variabili correlate, costruttore e metodi, che non ha funzionato neanche ... (e anche non poteva usare il contains.all, poiché non è non era "applicabile al mio cambiato variabile" ...)

ho esteso questo esempio, utilizzando la seconda realizzazione: https://gamedev.stackexchange.com/a/25652/48573

ho provato anche sui miei passi copiando il esempio verbatim. aggiunto

private static Set<BuildingTechTree> techsKnown; 

techsKnown = (BuildingTechTree.BIODOME); 
test = TechTrees.researchTech(techsKnown); 

in un'altra classe da richiamare per l'inizializzazione del test. e ho dovuto cambiare

public boolean researchTech(BuildingTechTree tech) { 

alla statica

Ciò ha provocato lo stesso errore "in non un enum". Non ho alcun rappresentante, per commentare la sua risposta a sottolineare l'errore di inizializzazione ...

Aggiunto informazioni per entrambe le risposte attuali, come entrambe le soluzioni provocano lo stesso nuovo errore:

public class TechTrees { 
private static Set<BuildingTechTree> techsKnown; 

public TechTrees() { 
    techsKnown = EnumSet.of(BuildingTechTree.NONE);  //Using this 
    techsKnown = EnumSet.noneOf(BuildingTechTree.class); //Or this 
} 

public static boolean researchTech(BuildingTechTree tech) { 
    if (techsKnown.containsAll(tech.requirements)) {  //Causes null pointer 
     return true;          //exception @ techsKnown 
    } 
    return false; 
} 
+0

Vedere la risposta modificata per il tuo secondo problema. –

risposta

9

La tua struttura di dichiarazione è così intelligente che è un peccato che non funzioni. Ma l'EnumSet sembra che l'enum debba essere completamente inizializzato per primo. Cerca di recuperare l'array di costanti dall'enumerazione in modo che, tra le altre cose, sappia quanto spazio sia necessario per il suo bitset interno.

Ecco una soluzione alternativa. Utilizza un metodo di supporto che crea innanzitutto un set ordinario (HashSet) e quindi, in un blocco di inizializzazione statico, itera le costanti enum e sostituisce tutti i set con EnumSet s.

public enum BuildingTechTree { 
    // Named constants 
    //Name      SoftName      Requirements 
    NONE      ("NULL",      null), 
    BARRACKS     ("Barracks",     setOf(NONE)), 
    WALLS_SANDBAGS    ("Sandbag wall",    setOf(NONE)), 
    POWERPLANT     ("Power plant",     setOf(BARRACKS)), 
    GUARDTOWER     ("Guard Tower",     setOf(BARRACKS)); 

    private final String softName; 
    private Set<BuildingTechTree> requirements; 

    private BuildingTechTree(String softName, Set<BuildingTechTree> requirements) { 
     this.softName = softName; 
     this.requirements = requirements; 
    } 

    private static Set<BuildingTechTree> setOf(BuildingTechTree... values) { 
     return new HashSet<>(Arrays.asList(values)); 
    } 

    static { 
     for (BuildingTechTree v : values()) { 
      if (v.requirements == null) { 
       v.requirements = EnumSet.noneOf(BuildingTechTree.class); 
      } else { 
       v.requirements = EnumSet.copyOf(v.requirements); 
      } 
     } 
    } 
} 
+0

, nessun errore di inizializzazione, tuttavia utilizzando set statico privato techsKnown; techsKnown = EnumSet.of (BuildingTechTree.NONE); causa che i tecnici noti come null, poiché sta ancora copiando il valore "null" originale per NONE, sembra non essere una copia profonda ... Cercherò di creare un altro "convertitore" come tuo solo per questo – user48573

+0

@ user48573 I don So cosa intendi. Funziona bene. Non ha bisogno di essere una "copia profonda" perché tutte le costanti enum sono singleton. – Boann

+0

Vedere le informazioni aggiunte alla fine della domanda – user48573

6

Hai un problema con uova e galline. Si potrebbe refactoring del enum a qualcosa di simile:

public enum BuildingTechTree { 

    NONE("NULL"), 
    BARRACKS("Barracks"), 
    WALLS_SANDBAGS("Sandbag wall"), 
    POWERPLANT("Power plant"), 
    GUARDTOWER("Guard Tower"); 

    static { 
     NONE.trees = EnumSet.noneOf(BuildingTechTree.class); 
     BARRACKS.trees = EnumSet.of(NONE); 
     WALLS_SANDBAGS.trees = EnumSet.of(NONE); 
     POWERPLANT.trees = EnumSet.of(BARRACKS); 
     GUARDTOWER.trees = EnumSet.of(BARRACKS); 
    } 

    private String name; 
    private Set<BuildingTechTree> trees; 

    private BuildingTechTree(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 

    public Set<BuildingTechTree> getTrees() { 
     return Collections.unmodifiableSet(trees); 
    } 
} 

EDIT:

per quanto riguarda il secondo problema: si sta accedendo una variabile statica, da un metodo statico. Ma questa variabile è inizializzata quando è stato chiamato il costruttore della classe (che è un enorme problema di progettazione). Non utilizzare campi statici non definitivi. E non inizializzare campi statici da metodi di istanza o costruttori. Non ha senso. Non si imposta il colore che dovrebbero avere tutte le auto quando si costruisce una macchina. Inizializza staticamente i tuoi campi statici:

public class TechTrees { 
    private static final Set<BuildingTechTree> TECHS_KNOWN = 
     EnumSet.of(BuildingTechTree.NONE); 

    public static boolean researchTech(BuildingTechTree tech) { 
     return TECHS_KNOWN.containsAll(tech.requirements)); 
    } 
} 
+1

Anche questa era una risposta valida, tuttavia mi obbligava a cambiare radicalmente il mio codice. Inoltre, con il mio progetto finale che prevede di avere oltre 100 edifici/unità all'interno di questa enumerazione, questa risposta avrebbe suddiviso ogni enumerazione in due sezioni, raddoppiando la quantità di linee, riducendo quindi la gestibilità e la leggibilità. +1 per l'idea, sono sicuro che ci sarà qualcuno che legge questo e trova uso per questo. e per la risposta e la spiegazione dettagliata per il mio secondo problema, – user48573

Problemi correlati