2012-04-12 7 views
27

Ho la seguente Enum:enumerazioni condiviso metodo statico look-up

public enum MyEnum{ 
    A(10, "First"), // 
    B(20, "Second"), // 
    C(35, "Other options"); 

    private Integer code; 
    private String description; 

    private MyEnum(Integer code, String description) { 
     this.code = code; 
     this.description = description; 
    } 

    public Integer getCode() { 
     return code; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public static MyEnum getValueOf(Integer code) { 
     for (MyEnum e : MyEnum.values()) { 
      if (e.getCode().equals(code)) { 
       return e; 
      } 
     } 
     throw new IllegalArgumentException("No enum const " + MyEnum.class.getName() + " for code \'" + code 
       + "\'"); 
    } 
} 

che funziona bene. Il metodo getValueOf esiste perché, quando comunichiamo con un partner esterno, otteniamo solo il codice (che hanno scelto) per mappare. Ho bisogno della descrizione perché ho bisogno di mostrare una frase significativa nella GUI.

Ma ora ho un numero di classi enum simili. Tutti con la propria descrizione del codice & e hanno bisogno della stessa funzionalità di ricerca. Volevo che il metodo getValueOf fosse generico, quindi non ho bisogno di supportare più di 30 enumerazioni per lo stesso metodo.

Per risolvere questo obiettivo, ho voluto creare una classe astratta per definire questo metodo e implementare alcune delle logiche comuni, ma ciò è impossibile perché non posso estendere Enum.

Poi ho provato a fare una classe di utilità con il seguente metodo:

public static <T extends Enum<T>> T getValueOf(Enum<T> type, Integer code) {...} 

Ma i farmaci generici con enumerazioni sono confusa e non capisco come ottenere questo lavoro.

Fondamentalmente quello che voglio sapere è: qual è un buon approccio per definire un'utilità comune a un enum?

risposta

22

È necessario passare l'oggetto classe enum effettivo come parametro al metodo. Quindi è possibile ottenere i valori enum utilizzando Class.getEnumConstants().

Al fine di essere in grado di accedere getCode() sulle istanze, è necessario definire in un'interfaccia e fare tutti i tipi di enum implementano tale interfaccia:

interface Encodable { 
    Integer getCode(); 
} 

public static <T extends Enum<T> & Encodable> T getValueOf(Class<T> enumClass, Integer code) { 
    for (T e : enumClass.getEnumConstants()) { 
     if (e.getCode().equals(code)) { 
      return e; 
     } 
    } 
    throw new IllegalArgumentException("No enum const " + enumClass.getName() + " for code \'" + code 
      + "\'"); 
} 

... 

public enum MyEnum implements Encodable { 
    ... 
} 

MyEnum e = getValueOf(MyEnum.class, 10); 
+0

FYI, il precedente potrebbe generare un NPE se getCode restituisce null. Vorrei mettere un check in 'if' condizionale per null. –

+0

@JohnB, davvero. Ho copiato il codice dall'OP e non mi sono preoccupato di migliorarlo. Se mai, invece di un controllo nullo, cambierei il tipo di 'codice' in' int' per stroncare il problema sul nascere. –

+1

In realtà l'ho preso e incorporato nel mio progetto di utilità. Fatto 'Encodable' generico quindi il metodo è diventato' statico pubblico & Encodable > T getValueOf (Classe enumClass, codice U) 'Spero non ti dispiaccia. –

7

Questo è un po 'complicato perché il metodo values() è statico. Avresti davvero bisogno di una riflessione, ma c'è un buon modo per nasconderlo usando le funzionalità della libreria standard.

In primo luogo, definire un'interfaccia con i metodi comuni a tutti i tipi enum:

public interface Common { 
    Integer getCode(); 
    String getDescription(); 
} 

Poi, fare tutti i vostri enumerazioni implementano questa interfaccia:

public enum MyEnum implements Common {...} 

Il metodo statico che si desidera sono quindi:

public static <T extends Enum<T> & Common> T getValueOf(Class<T> type, Integer code) { 
    final EnumSet<T> values = EnumSet.allOf(type); 
    for(T e : values) { 
     if(e.getCode().equals(code)) { 
      return e; 
     } 
    } 
    throw new IllegalArgumentException("No enum const " + type.getName() + " for code \'" + code + "\'"); 
} 
+0

Picchiato di 15 secondi, vabbè.L'unica cosa che cambierei è usare 'getEnumConstants()' invece di creare un EnumSet - che sembra un po 'inutile. – Voo

+0

@Voo Sì, praticamente la stessa risposta, ma non pensavo che molte persone lo avrebbero capito subito. ^^ Bene, gli EnumSet sono abbastanza efficienti, l'overhead dovrebbe essere basso, ma non conoscevo questo metodo per essere onesto. Non vedo uno svantaggio nell'usare 'getEnumConstants()', ma lascerò la mia risposta così com'è, perché c'è ancora un'altra risposta che la sta usando. –

+0

Il tuo commento mi lascia perplesso. Vedi una risposta aggiunta da @Voo? O a quale altra risposta ti riferisci? –

Problemi correlati