Cosa sono gli enum e perché sono utili?


488

Oggi stavo sfogliando alcune domande su questo sito e ho trovato la menzione di un enum utilizzo in modalità singleton sui presunti vantaggi di sicurezza del thread per tale soluzione.

Non ho mai usato enums e sto programmando in Java da più di un paio d'anni ormai. E apparentemente sono cambiati molto. Ora fanno persino il pieno sostegno di OOP dentro di sé.

Ora perché e perché dovrei usare enum nella programmazione quotidiana?



possibile duplicato di Enum in Java. I vantaggi?
Finnw

Non puoi istanziare enum perché ha un costruttore privato, sono istanziati all'avvio di jvm, quindi il suo singleton, Enums non sono thread-safe.
Arnav Joshi,

Risposte:


633

Dovresti sempre usare enum quando una variabile (specialmente un parametro di metodo) può prendere solo uno da un piccolo insieme di possibili valori. Esempi potrebbero essere costanti di tipo (stato del contratto: "permanente", "temp", "apprendista") o flag ("esegui ora", "differisci esecuzione").

Se si utilizzano enum invece di numeri interi (o codici String), si aumenta il controllo in fase di compilazione ed si evitano errori nel passaggio di costanti non valide e si documentano quali valori sono legali da utilizzare.

A proposito, un uso eccessivo di enum potrebbe significare che i tuoi metodi fanno troppo (spesso è meglio avere diversi metodi separati, piuttosto che un metodo che accetta più flag che modificano ciò che fa), ma se devi usare flag o digitare codici, enums sono la strada da percorrere.

Ad esempio, quale è meglio?

/** Counts number of foobangs.
 * @param type Type of foobangs to count. Can be 1=green foobangs,
 * 2=wrinkled foobangs, 3=sweet foobangs, 0=all types.
 * @return number of foobangs of type
 */
public int countFoobangs(int type)

contro

/** Types of foobangs. */
public enum FB_TYPE {
 GREEN, WRINKLED, SWEET, 
 /** special type for all types combined */
 ALL;
}

/** Counts number of foobangs.
 * @param type Type of foobangs to count
 * @return number of foobangs of type
 */
public int countFoobangs(FB_TYPE type)

Una chiamata di metodo come:

int sweetFoobangCount = countFoobangs(3);

quindi diventa:

int sweetFoobangCount = countFoobangs(FB_TYPE.SWEET);

Nel secondo esempio, è immediatamente chiaro quali tipi sono consentiti, i documenti e l'implementazione non possono andare fuori sincrono e il compilatore può imporlo. Inoltre, una chiamata non valida come

int sweetFoobangCount = countFoobangs(99);

non è più possibile.


41
Se usi enum e vuoi consentire una combinazione di valori, usa EnumSet. Questo viene fornito con tutti i tipi di helper ordinati, come EnumSet <FB_TYPE> ALL statico pubblico ALL = EnumSet.allOf (FB_TYPE.class);
RobAu,

20
Queste risposte sono quelle che mi piacciono molto vedere a SO perché qualcuno ci ha fatto un vero sforzo, buon lavoro ora capisco le enumerazioni!
Dediq

1
Non penso sia vero you should *always* use enums when a variable can only take one out of a small set of possible values. L'uso di valori costanti come 'flag binario' (con oring logico ) può essere utile per applicazioni in tempo reale in cui la memoria è insufficiente.
Elist,

@Elist usando enum aumenta la leggibilità dei tuoi codici, se usi le costanti in qualche momento tu o il tuo successore non sapete perché viene usato ...
:)

136

Perché utilizzare una funzione del linguaggio di programmazione? Il motivo per cui abbiamo le lingue è per

  1. I programmatori possono esprimere in modo efficiente e corretto algoritmi in una forma che i computer possono usare.
  2. I manutentori per capire gli algoritmi che altri hanno scritto e apportare correttamente le modifiche.

Gli enum migliorano sia la probabilità di correttezza che la leggibilità senza scrivere molta piastra di caldaia. Se sei disposto a scrivere boilerplate, allora puoi "simulare" enum:

public class Color {
    private Color() {} // Prevent others from making colors.
    public static final Color RED = new Color();
    public static final Color AMBER = new Color();
    public static final Color GREEN = new Color();
}

Ora puoi scrivere:

Color trafficLightColor = Color.RED;

La targhetta sopra ha lo stesso effetto di

public enum Color { RED, AMBER, GREEN };

Entrambi forniscono lo stesso livello di controllo della guida dal compilatore. Boilerplate è solo più digitando. Ma salvare un sacco di digitazione rende il programmatore più efficiente (vedi 1), quindi è una funzione utile.

Vale la pena anche per almeno un'altra ragione:

Istruzioni switch

Una cosa che la static finalsimulazione enum di cui sopra non ti dà sono i bei switchcasi. Per i tipi di enum, lo switch Java utilizza il tipo della sua variabile per inferire l'ambito dei casi enum, quindi per quanto enum Colorsopra devi semplicemente dire:

Color color = ... ;
switch (color) {
    case RED:
        ...
        break;
}

Nota che non è Color.REDnei casi. Se non usi enum, l'unico modo per usare le quantità con nome switchè qualcosa di simile a:

public Class Color {
    public static final int RED = 0;
    public static final int AMBER = 1;
    public static final int GREEN = 2;
}

Ma ora una variabile per contenere un colore deve avere tipo int. Il piacevole compilatore che controlla l'enum e ilstatic final simulazione è sparito. Non felice.

Un compromesso consiste nell'utilizzare un membro con valore scalare nella simulazione:

public class Color {
    public static final int RED_TAG = 1;
    public static final int AMBER_TAG = 2;
    public static final int GREEN_TAG = 3;

    public final int tag;

    private Color(int tag) { this.tag = tag; } 
    public static final Color RED = new Color(RED_TAG);
    public static final Color AMBER = new Color(AMBER_TAG);
    public static final Color GREEN = new Color(GREEN_TAG);
}

Adesso:

Color color = ... ;
switch (color.tag) {
    case Color.RED_TAG:
        ...
        break;
}

Ma nota, ancora più boilerplate!

Usando un enum come singleton

Dalla piastra sopra riportata puoi vedere perché un enum fornisce un modo per implementare un singleton. Invece di scrivere:

public class SingletonClass {
    public static final void INSTANCE = new SingletonClass();
    private SingletonClass() {}

    // all the methods and instance data for the class here
}

e poi accedendo con

SingletonClass.INSTANCE

possiamo solo dire

public enum SingletonClass {
    INSTANCE;

    // all the methods and instance data for the class here
}

che ci dà la stessa cosa. Possiamo evitarlo perché gli enum Java sono implementati come classi complete con solo un po 'di zucchero sintattico cosparso sopra. Questo è di nuovo meno targhetta, ma non è ovvio a meno che il linguaggio non ti sia familiare. Non mi piace anche il fatto che ottieni le varie funzioni enum anche se non hanno molto senso per il singleton: orde values, ecc. (In realtà c'è una simulazione più complicata in cui Color extends Integerfunzionerà con switch, ma è così complicato che è ancora più mostra chiaramente perché enumè un'idea migliore.)

Sicurezza del filo

La sicurezza del thread è un potenziale problema solo quando i singoli vengono creati pigramente senza blocco.

public class SingletonClass {
    private static SingletonClass INSTANCE;
    private SingletonClass() {}
    public SingletonClass getInstance() {
        if (INSTANCE == null) INSTANCE = new SingletonClass();
        return INSTANCE;
    }

    // all the methods and instance data for the class here
}

Se molti thread chiamano getInstancecontemporaneamente mentre INSTANCEè ancora nullo, è possibile creare un numero qualsiasi di istanze. Questo non va bene. L'unica soluzione è aggiungere l' synchronizedaccesso per proteggere la variabile INSTANCE.

Tuttavia, il static finalcodice sopra non presenta questo problema. Crea l'istanza avidamente al momento del caricamento della classe. Il caricamento della classe è sincronizzato.

Il enumsingleton è effettivamente pigro perché non è inizializzato fino al primo utilizzo. Anche l'inizializzazione Java è sincronizzata, quindi più thread non possono inizializzare più di un'istanza di INSTANCE. Stai ricevendo un singleton pigramente inizializzato con pochissimo codice. L'unico aspetto negativo è la sintassi piuttosto oscura. Devi conoscere il linguaggio o comprendere a fondo come funzionano il caricamento e l'inizializzazione della classe per sapere cosa sta succedendo.


15
Quest'ultimo paragrafo ha davvero chiarito la situazione singleton per me. Grazie! Ogni lettore che sta scremando dovrebbe rileggerlo.
Basil Bourque,

Stavo leggendo questo, stackoverflow.com/questions/16771373/… . Ora sono confuso con il tuo ultimo paragrafo. In che modo enum non fornisce funzionalità di inizializzazione laica?
Deepankar Singh,

static finali campi vengono inizializzati al momento dell'inizializzazione della classe , non al momento del caricamento. È esattamente lo stesso che con enuml'inizializzazione costante (in effetti, sono identici sotto il cofano). Ecco perché cercare di implementare un codice di inizializzazione "intelligente" per i singleton è sempre stato inutile, anche nella prima versione di Java.
Holger,

42

Oltre ai già citati casi d'uso, trovo spesso utili enumerazioni per l'implementazione del modello di strategia, seguendo alcune linee guida OOP di base:

  1. Avere il codice in cui si trovano i dati (vale a dire, all'interno dell'enum stesso - o spesso all'interno delle costanti dell'enum, che può sovrascrivere i metodi).
  2. Implementare un'interfaccia (o più) per non associare il codice client all'enum (che dovrebbe fornire solo una serie di implementazioni predefinite).

L'esempio più semplice sarebbe un insieme di Comparatorimplementazioni:

enum StringComparator implements Comparator<String> {
    NATURAL {
        @Override
        public int compare(String s1, String s2) {
            return s1.compareTo(s2);
        }
    },
    REVERSE {
        @Override
        public int compare(String s1, String s2) {
            return NATURAL.compare(s2, s1);
        }
    },
    LENGTH {
        @Override
        public int compare(String s1, String s2) {
            return new Integer(s1.length()).compareTo(s2.length());
        }
    };
}

Questo "modello" può essere utilizzato in scenari molto più complessi, facendo ampio uso di tutte le chicche che derivano dall'enum: iterare sulle istanze, fare affidamento sul loro ordine implicito, recuperare un'istanza con il suo nome, metodi statici che forniscono l'istanza giusta per contesti specifici ecc. Eppure hai tutto questo nascosto dietro l'interfaccia, quindi il tuo codice funzionerà con implementazioni personalizzate senza modifiche nel caso in cui desideri qualcosa che non è disponibile tra le "opzioni predefinite".

Ho visto questo applicato con successo per modellare il concetto di granularità temporale (giornaliera, settimanale, ecc.) In cui tutta la logica era incapsulata in un enum (scegliendo la granularità giusta per un determinato intervallo di tempo, comportamento specifico legato a ciascuna granularità come costante metodi ecc.). Eppure, Granularitycome visto dal livello di servizio era semplicemente un'interfaccia.


2
Puoi anche aggiungere CASE_INSENSITIVE { @Override public int compare(String s1, String s2) { return s1.compareToIgnoreCase(s2); }. Un vantaggio non ancora menzionato è che si ottiene un solido supporto di serializzazione; il modulo persistente contiene solo il nome della classe e il nome costante, non in base ai dettagli di implementazione dei comparatori.
Holger,

32

Qualcosa che nessuna delle altre risposte ha coperto che rende gli enum particolarmente potenti è la possibilità di avere metodi di template . I metodi possono far parte dell'enum di base e sovrascritti da ciascun tipo. E, con il comportamento associato all'enum, spesso elimina la necessità di costrutti if-else o di istruzioni switch come dimostra questo post sul blog - dove si enum.method()trova ciò che originariamente verrebbe eseguito all'interno del condizionale. Lo stesso esempio mostra anche l'uso di importazioni statiche con enum e produce codice DSL molto più pulito.

Alcune altre qualità interessanti includono il fatto che gli enum forniscono implementazione per equals(), toString()e hashCode()e implementano Serializablee Comparable.

Per una carrellata completa di tutto ciò che enum ha da offrire, consiglio vivamente la 4a edizione di Bruce Eckel Thinking in Java che dedica un intero capitolo all'argomento. Particolarmente illuminanti sono gli esempi che coinvolgono un gioco Rock, Paper, Scissors (cioè RoShamBo) come enumerazioni.


23

Dai documenti Java -

È necessario utilizzare i tipi di enum ogni volta che è necessario rappresentare un insieme fisso di costanti. Ciò include tipi di enum naturali come i pianeti nel nostro sistema solare e set di dati in cui si conoscono tutti i possibili valori in fase di compilazione, ad esempio le scelte su un menu, i flag della riga di comando e così via.

Un esempio comune è quello di sostituire una classe con un insieme di costanti int finali statiche private (entro un numero ragionevole di costanti) con un tipo enum. Fondamentalmente se pensi di conoscere tutti i possibili valori di "qualcosa" in fase di compilazione puoi rappresentarlo come un tipo enum. Gli enum forniscono leggibilità e flessibilità rispetto a una classe con costanti.

Pochi altri vantaggi che posso pensare ai tipi di enum. Sono sempre un'istanza di una particolare classe enum (da cui il concetto di usare enum come arriva singleton). Un altro vantaggio è che puoi usare enum come tipo nell'istruzione switch-case. Inoltre puoi usare toString () sull'enum per stamparli come stringhe leggibili.


8
Utilizzeresti un enum per tutti i 366 giorni dell'anno? È un insieme fisso (366) di costanti (i giorni non cambiano). Quindi questo suggerisce che dovresti. : - / Vincolerei la dimensione del set fisso.
Moinudin,

2
@marcog Con un po 'di pensiero intelligente potrebbe essere possibile riassumere giorni di una settimana e giorni di ogni mese in un enum compatto.
James P.

1
A proposito di giorni della settimana ... DayOfWeekenum è ora predefinito, integrato in Java 8 e versioni successive come parte del framework java.time (e trasferito a Java 6 & 7 e Android ).
Basil Bourque,

19

Ora, perché e perché dovrei usare enum nella programmazione quotidiana?

È possibile utilizzare un Enum per rappresentare un insieme fisso di piccole costanti o una modalità di classe interna aumentando la leggibilità. Inoltre, Enums può applicare una certa rigidità quando viene utilizzato nei parametri del metodo. Offrono l'interessante possibilità di passare informazioni a un costruttore come nell'esempio dei pianeti sul sito di Oracle e, come hai scoperto, consentono anche un modo semplice per creare un modello singleton.

es: Locale.setDefault(Locale.US)legge meglio di Locale.setDefault(1)e impone l'uso dell'insieme fisso di valori mostrato in un IDE quando aggiungi il .separatore invece di tutti i numeri interi.


@arnt Ho anche corretto la grammatica nella domanda. Grazie.
James P.

13

Enums enumera un insieme fisso di valori, in modo auto-documentante.
Rendono il tuo codice più esplicito e anche meno soggetto a errori.

Perché non usare String, o int, invece di Enum, per le costanti?

  1. Il compilatore non consentirà errori di battitura , né valori al di fuori dell'insieme fisso, poiché gli enum sono tipi da soli. conseguenze:
    • Non dovrai scrivere una pre-condizione (o un manuale if) per assicurarti che l'argomento sia compreso nell'intervallo valido.
    • Il tipo invariant è disponibile gratuitamente.
  2. Gli enum possono avere un comportamento, proprio come qualsiasi altra classe.
  3. Probabilmente avresti bisogno di una quantità simile di memoria per usare Strings, comunque (questo dipende dalla complessità del Enum).

Inoltre, ciascuna delle Enumistanze è una classe, per la quale è possibile definire il suo comportamento individuale.

Inoltre, garantiscono la sicurezza dei thread durante la creazione delle istanze (quando viene caricato l'enum), che ha visto una grande applicazione nella semplificazione del modello Singleton .

Questo blog illustra alcune delle sue applicazioni, come una macchina a stati per un parser.


13

È utile sapere che enumssono proprio come le altre classi con Constantcampi e a private constructor.

Per esempio,

public enum Weekday
{
  MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
} 

Il compilatore lo compila come segue;

class Weekday extends Enum
{
  public static final Weekday MONDAY  = new Weekday( "MONDAY",   0 );
  public static final Weekday TUESDAY = new Weekday( "TUESDAY ", 1 );
  public static final Weekday WEDNESDAY= new Weekday( "WEDNESDAY", 2 );
  public static final Weekday THURSDAY= new Weekday( "THURSDAY", 3 );
  public static final Weekday FRIDAY= new Weekday( "FRIDAY", 4 );
  public static final Weekday SATURDAY= new Weekday( "SATURDAY", 5 );
  public static final Weekday SUNDAY= new Weekday( "SUNDAY", 6 );

  private Weekday( String s, int i )
  {
    super( s, i );
  }

  // other methods...
}

12

enumsignifica enumerazione, cioè menzione (un numero di cose) una per una.

Un enum è un tipo di dati che contiene un set fisso di costanti.

O

An enumè proprio come un class, con un set fisso di istanze conosciute al momento della compilazione.

Per esempio:

public class EnumExample {
    interface SeasonInt {
        String seasonDuration();
    }

    private enum Season implements SeasonInt {
        // except the enum constants remaining code looks same as class
        // enum constants are implicitly public static final we have used all caps to specify them like Constants in Java
        WINTER(88, "DEC - FEB"), SPRING(92, "MAR - JUN"), SUMMER(91, "JUN - AUG"), FALL(90, "SEP - NOV");

        private int days;
        private String months;

        Season(int days, String months) { // note: constructor is by default private 
            this.days = days;
            this.months = months;
        }

        @Override
        public String seasonDuration() {
            return this+" -> "+this.days + "days,   " + this.months+" months";
        }

    }
    public static void main(String[] args) {
        System.out.println(Season.SPRING.seasonDuration());
        for (Season season : Season.values()){
            System.out.println(season.seasonDuration());
        }

    }
}

Vantaggi dell'enum:

  • enum migliora la sicurezza dei tipi durante il controllo in fase di compilazione per evitare errori in fase di esecuzione.
  • enum può essere facilmente utilizzato in switch
  • enum può essere attraversato
  • enum può avere campi, costruttori e metodi
  • enum può implementare molte interfacce ma non può estendere alcuna classe perché estende internamente la classe Enum

per di più


9

Che cos'è un enum

  • enum è una parola chiave definita per l'Enumerazione di un nuovo tipo di dati. Le enumerazioni typesafe dovrebbero essere usate liberamente. In particolare, rappresentano una valida alternativa alla semplice stringa o costanti int utilizzate in API molto più vecchie per rappresentare insiemi di elementi correlati.

Perché usare enum

  • gli enum sono sottoclassi implicitamente finali di java.lang.Enum
  • se un enum è un membro di una classe, è implicitamente statico
  • new non può mai essere usato con un enum, nemmeno all'interno del tipo enum stesso
  • nome e valore di utilizzare semplicemente il testo delle costanti enum, mentre toString può essere ignorato per fornire qualsiasi contenuto, se lo si desidera
  • per enum costanti, uguale e == ammontano alla stessa cosa e possono essere usati in modo intercambiabile
  • le costanti di enum sono implicitamente pubbliche statiche finali

Nota

  • enum non può estendere nessuna classe.
  • Un enum non può essere una superclasse.
  • l'ordine di apparizione delle costanti di enum è chiamato il loro "ordine naturale" e definisce anche l'ordine usato da altri elementi: compareTo, ordine di valori di iterazione, EnumSet, EnumSet.range.
  • Un'enumerazione può avere costruttori, blocchi statici e di istanza, variabili e metodi ma non può avere metodi astratti.

4
Non spieghi perché usare enums. È sufficiente elencare diverse proprietà degli enum in intestazioni non correlate.
Duncan Jones,

@DuncanJones i termini final, static non danno lo scopo di usare enums?
tinker_fairy,

8

A parte tutto ciò che è stato detto da altri ... In un vecchio progetto per cui lavoravo, molta comunicazione tra entità (applicazioni indipendenti) utilizzava numeri interi che rappresentavano un piccolo insieme. È stato utile dichiarare il set come enumcon metodi statici per ottenere l' enumoggetto valuee viceversa. Il codice sembrava più pulito, cambia l'usabilità del case e facilita la scrittura nei log.

enum ProtocolType {
    TCP_IP (1, "Transmission Control Protocol"), 
    IP (2, "Internet Protocol"), 
    UDP (3, "User Datagram Protocol");

    public int code;
    public String name;

    private ProtocolType(int code, String name) {
        this.code = code;
        this.name = name;
    }

    public static ProtocolType fromInt(int code) {
    switch(code) {
    case 1:
        return TCP_IP;
    case 2:
        return IP;
    case 3:
        return UDP;
    }

    // we had some exception handling for this
    // as the contract for these was between 2 independent applications
    // liable to change between versions (mostly adding new stuff)
    // but keeping it simple here.
    return null;
    }
}

Creare l' enumoggetto dai valori ricevuti (ad es. 1,2) utilizzandoProtocolType.fromInt(2) Scrivi nei registri usandomyEnumObj.name

Spero che sia di aiuto.


6

Enum eredita tutti i metodi di Objectclasse e classe astratta Enum. Quindi puoi usare i suoi metodi di riflessione, multithreading, serilization, comparabili, ecc. Se dichiari semplicemente una costante statica invece di Enum, non puoi. Oltre a ciò, il valore di Enum può essere passato anche al livello DAO.

Ecco un esempio di programma da dimostrare.

public enum State {

    Start("1"),
    Wait("1"),
    Notify("2"),
    NotifyAll("3"),
    Run("4"),
    SystemInatilize("5"),
    VendorInatilize("6"),
    test,
    FrameworkInatilize("7");

    public static State getState(String value) {
        return State.Wait;
    }

    private String value;
    State test;

    private State(String value) {
        this.value = value;
    }

    private State() {
    }

    public String getValue() {
        return value;
    }

    public void setCurrentState(State currentState) {
        test = currentState;
    }

    public boolean isNotify() {
        return this.equals(Notify);
    }
}

public class EnumTest {

    State test;

    public void setCurrentState(State currentState) {
        test = currentState;
    }

    public State getCurrentState() {
        return test;
    }

    public static void main(String[] args) {
        System.out.println(State.test);
        System.out.println(State.FrameworkInatilize);
        EnumTest test=new EnumTest();
        test.setCurrentState(State.Notify);
        test. stateSwitch();
    }

    public void stateSwitch() {
        switch (getCurrentState()) {
        case Notify:
            System.out.println("Notify");
            System.out.println(test.isNotify());
            break;
        default:
            break;
        }
    }
}

4

ENum sta per "Tipo enumerato". È un tipo di dati con un set fisso di costanti che tu definisci.


Non hai spiegato perché usare un enum.
Duncan Jones,

4
Si l'ho fatto. Lo usi per memorizzare un insieme fisso di costanti che definisci te stesso. L'applicazione specifica dipende da te. Non è possibile dire quando, perché o come usare qualcosa. Questo dipende dalle esigenze dello sviluppatore. Tutto quello che devi capire è cos'è e come funziona.
Steve,

4

Secondo me, tutte le risposte che hai ottenuto fino ad ora sono valide, ma secondo la mia esperienza, lo esprimerei in poche parole:

Utilizzare enum se si desidera che il compilatore controlli la validità del valore di un identificatore.

Altrimenti, puoi usare le stringhe come hai sempre fatto (probabilmente hai definito alcune "convenzioni" per la tua applicazione) e sarai molto flessibile ... ma non otterrai la sicurezza al 100% contro errori di battitura sulle tue stringhe e te ne accorgerai solo in fase di esecuzione.


3

Usa enum per TYPE SAFETY, questa è una funzione linguistica, quindi di solito otterrai:

  • Supporto del compilatore (vedi immediatamente problemi di tipo)
  • Supporto dello strumento negli IDE (completamento automatico in caso di cambio, casi mancanti, forzatura predefinita, ...)
  • In alcuni casi anche le prestazioni enum sono eccezionali ( EnumSet , alternativa tipica ai tradizionali "bit flag" basati su int ).

Gli enum possono avere metodi, costruttori, puoi persino usare enum dentro enum e combinare enum con interfacce.

Pensa agli enum come tipi per sostituire un insieme ben definito di costanti int (che Java ha "ereditato" da C / C ++) e in alcuni casi per sostituire i bit flag.

Il libro Effective Java 2nd Edition ha un intero capitolo su di loro e approfondisce i dettagli. Vedi anche questo post Stack Overflow .


2

Java consente di limitare la variabile al solo uno dei pochi valori predefiniti, ovvero un valore da un elenco elencato. L'uso enumspuò aiutare a ridurre i bug nel tuo codice. Ecco un esempio di enumsfuori di una classe:

enums coffeesize{BIG , HUGE , OVERWHELMING }; 
//This semicolon is optional.

Ciò limita coffeesizead avere entrambi: BIG, HUGEo OVERWHELMINGcome variabile.


2

Enum? Perché dovrebbe essere usato? Penso che sia più chiaro quando lo userai. Ho la stessa esperienza

Supponiamo che tu abbia un'operazione di creazione, eliminazione, modifica e lettura del database.

Ora se crei un enum come operazione:

public enum operation {
    create("1")
    delete("2")
    edit("3")
    read("4")

    // You may have is methods here
    public boolean isCreate() {
        return this.equals(create);
    }
    // More methods like the above can be written

}

Ora puoi dichiarare qualcosa del tipo:

private operation currentOperation;

// And assign the value for it 
currentOperation = operation.create

Quindi puoi usarlo in molti modi. È sempre utile avere enum per cose specifiche poiché l'operazione di database nell'esempio sopra può essere controllata controllando currentOperation . Forse si può dire che ciò può essere realizzato anche con variabili e valori interi. Ma credo che Enum sia un modo più sicuro e programmatore.

Un'altra cosa: penso che ogni programmatore ami il booleano , vero? Perché può memorizzare solo due valori, due valori specifici. Quindi si può pensare che Enum abbia lo stesso tipo di strutture in cui un utente definirà quante e che tipo di valore memorizzerà, solo in un modo leggermente diverso. :)


1

Finora non ho mai avuto bisogno di usare enum. Ho letto su di loro da quando sono stati introdotti in 1.5 o versione Tiger come è stato richiamato in quel giorno. Non hanno mai veramente risolto un "problema" per me. Per coloro che lo usano (e vedo che molti di loro lo fanno), sono sicuro che abbia sicuramente uno scopo. Solo i miei 2 sterline.



1

Ciò che mi ha dato il momento Ah-Ha è stata questa realizzazione: che Enum ha un costruttore privato accessibile solo tramite l'enumerazione pubblica:

enum RGB {
    RED("Red"), GREEN("Green"), BLUE("Blue");

    public static final String PREFIX = "color ";

    public String getRGBString() {
        return PREFIX + color;
    }

    String color;

    RGB(String color) {
        this.color = color;
    }
}

public class HelloWorld {
    public static void main(String[] args) {
        String c = RGB.RED.getRGBString();
        System.out.print("Hello " + c);
    }
}

1

Quanto a me per rendere il codice leggibile in futuro, il caso utile più utile di enumerazione è rappresentato nel frammento seguente:

public enum Items {
    MESSAGES, CHATS, CITY_ONLINE, FRIENDS, PROFILE, SETTINGS, PEOPLE_SEARCH, CREATE_CHAT
}

@Override
public boolean onCreateOptionsMenu(Menu menuPrm) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menuPrm);
    View itemChooserLcl;
    for (int i = 0; i < menuPrm.size(); i++) {
        MenuItem itemLcl  = menuPrm.getItem(i);
            itemChooserLcl = itemLcl.getActionView();
            if (itemChooserLcl != null) {
                 //here Im marking each View' tag by enume values:
                itemChooserLcl.setTag(Items.values()[i]);
                itemChooserLcl.setOnClickListener(drawerMenuListener);
            }
        }
    return true;
}
private View.OnClickListener drawerMenuListener=new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Items tagLcl= (Items) v.getTag();
        switch (tagLcl){
            case MESSAGES: ;
            break;
            case CHATS : ;
            break;
            case CITY_ONLINE : ;
            break;
            case FRIENDS : ;
            break;
            case  PROFILE: ;
            break;
            case  SETTINGS: ;
            break;
            case  PEOPLE_SEARCH: ;
            break;
            case  CREATE_CHAT: ;
            break;
        }
    }
};

1

Nella mia esperienza ho visto che l'utilizzo di Enum a volte rende i sistemi molto difficili da cambiare. Se stai usando un Enum per un set di valori specifici del dominio che cambiano frequentemente e ha molte altre classi e componenti che dipendono da esso, potresti considerare di non usare un Enum.

Ad esempio, un sistema di trading che utilizza un Enum per mercati / scambi. Ci sono molti mercati là fuori ed è quasi certo che ci saranno molti sottosistemi che devono accedere a questo elenco di mercati. Ogni volta che vuoi aggiungere un nuovo mercato al tuo sistema, o se vuoi rimuovere un mercato, è possibile che tutto ciò che è sotto il sole dovrà essere ricostruito e rilasciato.

Un esempio migliore potrebbe essere qualcosa di simile a un tipo di categoria di prodotto. Supponiamo che il tuo software gestisca l'inventario per un grande magazzino. Esistono molte categorie di prodotti e molte ragioni per cui questo elenco di categorie potrebbe cambiare. I manager potrebbero voler immagazzinare una nuova linea di prodotti, sbarazzarsi di altre linee di prodotti e possibilmente riorganizzare le categorie di volta in volta. Se devi ricostruire e ridistribuire tutti i tuoi sistemi semplicemente perché gli utenti vogliono aggiungere una categoria di prodotti, allora hai preso qualcosa che dovrebbe essere semplice e veloce (aggiungendo una categoria) e lo ha reso molto difficile e lento.

In conclusione, gli Enum sono buoni se i dati che rappresentate sono molto statici nel tempo e hanno un numero limitato di dipendenze. Ma se i dati cambiano molto e hanno molte dipendenze, allora hai bisogno di qualcosa di dinamico che non viene controllato al momento della compilazione (come una tabella di database).


1

Il singleton basato sull'enum

uno sguardo moderno a un vecchio problema

Questo approccio implementa il singleton sfruttando la garanzia di Java che ogni valore enum viene istanziato una sola volta in un programma Java e enum fornisce un supporto implicito per la sicurezza dei thread. Poiché i valori di enum Java sono accessibili a livello globale, quindi possono essere utilizzati come singleton.

public enum Singleton {
    SINGLETON; 
    public void method() { }
}

Come funziona? Bene, la riga due del codice può essere considerata in questo modo:

public final static Singleton SINGLETON = new Singleton(); 

E otteniamo un buon vecchio singleton inizializzato in anticipo.

Ricorda che, poiché si tratta di un enum, puoi sempre accedere all'istanza anche tramite Singleton.INSTANCE:

Singleton s = Singleton.INSTANCE;
vantaggi
  • Per impedire la creazione di altre istanze di singleton durante la deserializzazione, utilizzare singleton basato su enum poiché JVM si occupa della serializzazione di enum. La serializzazione e la deserializzazione di Enum funzionano in modo diverso rispetto ai normali oggetti Java. L'unica cosa che viene serializzata è il nome del valore enum. Durante il processo di deserializzazione l'enumvalueOf metodo viene utilizzato con il nome deserializzato per ottenere l'istanza desiderata.
  • Singleton basato su Enum consente di proteggersi dagli attacchi di riflessione. Il tipo enum estende effettivamente la Enumclasse java . Il motivo per cui la riflessione non può essere utilizzata per creare un'istanza di oggetti di tipo enum è perché la specifica java non consente e tale regola è codificata nell'implementazione del newInstancemetodo della Constructorclasse, che di solito viene utilizzata per creare oggetti tramite la riflessione:
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
    throw new IllegalArgumentException("Cannot reflectively create enum objects");
  • Enum non dovrebbe essere clonato perché deve esserci esattamente un'istanza di ciascun valore.
  • Il codice più laconico tra tutte le realizzazioni singleton.
svantaggi
  • Il singleton basato su enum non consente l'inizializzazione lazy.
  • Se hai cambiato il tuo design e volessi convertire il tuo singleton in multiton, enum non lo permetterebbe. Il modello multitono viene utilizzato per la creazione controllata di più istanze, che gestisce mediante l'uso di a map. Invece di avere una singola istanza per applicazione (ad esempio il java.lang.Runtime) il modello multitono garantisce invece una singola istanza per chiave .
  • Enum appare solo in Java 5, quindi non puoi usarlo nella versione precedente.

Esistono diverse realizzazioni del modello singleton ognuna con vantaggi e svantaggi.

  • Desideroso caricamento di singleton
  • Singleton di blocco con doppio controllo
  • Idioma del titolare di inizializzazione su richiesta
  • Il singleton basato sull'enum

Una descrizione dettagliata di ognuno di essi è troppo dettagliata, quindi ho messo un link a un buon articolo - Tutto quello che vuoi sapere su Singleton


0

Vorrei usare enum come utile strumento di mappatura, evitando il multiplo if-else purché siano implementati alcuni metodi.

public enum Mapping {

    ONE("1"),
    TWO("2");

    private String label;

    private Mapping(String label){
        this.label = label;
    }

    public static Mapping by(String label) {

        for(Mapping m: values() {
            if(m.label.equals(label)) return m;
        }

        return null;
    }

}

Quindi il metodo by(String label) consente di ottenere il valore Enumerato da non elencato. Inoltre, si può inventare la mappatura tra 2 enumerazioni. Potrebbe anche provare "1 a molti" o "molti a molti" oltre alla relazione predefinita "uno a uno"

Alla fine, enumè una classe Java. Quindi puoi avere un mainmetodo al suo interno, che potrebbe essere utile quando devi eseguire subito alcune operazioni di mappatura args.


0

Invece di fare un mucchio di dichiarazioni const int

Puoi raggrupparli tutti in 1 enum

Quindi è tutto organizzato dal gruppo comune a cui appartengono


0

Gli enum sono come le classi. Come la classe, ha anche metodi e attributi.

Le differenze con la classe sono: 1. Le costanti enum sono pubbliche, statiche, finali. 2. un enum non può essere usato per creare un oggetto e non può estendere altre classi. Ma può implementare interfacce.


0

Oltre alla risposta di @BradB:

È così vero ... È strano che sia l'unica risposta a menzionarlo. Quando i principianti scoprono le enumerazioni, lo prendono rapidamente come un trucco magico per un valido identificatore che controlla il compilatore. E quando il codice è destinato a essere utilizzato su sistemi distribuiti, piangono ... qualche mese dopo. Mantenere la retrocompatibilità con gli enum che contengono un elenco di valori non statici è una vera preoccupazione e dolore. Questo perché quando aggiungi un valore a un enum esistente, il suo tipo cambia (nonostante il nome non lo faccia).

"Ho, aspetta, potrebbe sembrare lo stesso tipo, giusto? Dopotutto, sono enumerazioni con lo stesso nome - e non sono enumerazioni solo numeri interi sotto il cofano?" E per questi motivi, il compilatore probabilmente non contrassegnerà l'uso di una definizione del tipo stesso in cui si aspettava l'altra. Ma in realtà, sono (nei modi più importanti) tipi diversi. Soprattutto, hanno domini di dati diversi - valori accettabili dato il tipo. Aggiungendo un valore, abbiamo effettivamente modificato il tipo di enum e quindi interrotto la retrocompatibilità.

In conclusione: usalo quando vuoi, ma, per favore, controlla che il dominio di dati usato sia un set fisso, già noto, fisso .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.