¿Qué son las enumeraciones y por qué son útiles?

488

Hoy estaba navegando por algunas preguntas en este sitio y encontré una mención de un enum ser utilizado en un patrón único sobre los supuestos beneficios de seguridad de los hilos para dicha solución.

Nunca he usado enumsy he estado programando en Java durante más de un par de años. Y aparentemente cambiaron mucho. Ahora incluso hacen un apoyo total de OOP dentro de sí mismos.

Ahora, ¿por qué y para qué debo usar enum en la programación diaria?

Mat B.
fuente
posible duplicado de Enum en Java. Ventajas?
finnw
No puede crear instancias de enumeraciones porque tiene un constructor privado, se crean instancias en el inicio de jvm, por lo que es único, las enumeraciones no son seguras para subprocesos.
Arnav Joshi

Respuestas:

633

Siempre debe usar enumeraciones cuando una variable (especialmente un parámetro de método) solo puede extraer una de un pequeño conjunto de valores posibles. Los ejemplos serían cosas como constantes de tipo (estado del contrato: "permanente", "temp", "aprendiz") o banderas ("ejecutar ahora", "diferir la ejecución").

Si usa enumeraciones en lugar de números enteros (o códigos de cadena), aumenta la verificación en tiempo de compilación y evita que los errores pasen constantes no válidas, y documenta qué valores son legales para usar.

Por cierto, el uso excesivo de enumeraciones puede significar que sus métodos hacen demasiado (a menudo es mejor tener varios métodos separados, en lugar de un método que tome varios indicadores que modifiquen lo que hace), pero si tiene que usar indicadores o códigos de tipo, enumeraciones son el camino a seguir.

Como ejemplo, ¿cuál es mejor?

/** 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)

versus

/** 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 llamada a un método como:

int sweetFoobangCount = countFoobangs(3);

luego se convierte en:

int sweetFoobangCount = countFoobangs(FB_TYPE.SWEET);

En el segundo ejemplo, queda claro de inmediato qué tipos están permitidos, los documentos y la implementación no pueden estar fuera de sincronización, y el compilador puede aplicar esto. Además, una llamada no válida como

int sweetFoobangCount = countFoobangs(99);

Ya no es posible.

sleske
fuente
41
Si usa enumeraciones y desea permitir una combinación de valores, use EnumSet. Esto viene con todo tipo de ayudantes ordenados, como Public static final EnumSet <FB_TYPE> ALL = EnumSet.allOf (FB_TYPE.class);
RobAu
20
Estas respuestas son las que realmente me gusta ver en SO porque alguien ha puesto un esfuerzo real en ello, ¡buen trabajo ahora entiendo enumeraciones!
Dedicado el
1
No creo que sea fiel a eso you should *always* use enums when a variable can only take one out of a small set of possible values. Usar valores constantes como 'indicador binario' (con lógica or) puede ser útil para aplicaciones en tiempo real en las que tiene poca memoria.
Elist
@Elist usando enumeraciones aumenta la legibilidad de sus códigos, si usa constantes en algún momento usted o su sucesor no sabe por qué se usa ...
:)
136

¿Por qué usar cualquier función de lenguaje de programación? La razón por la que tenemos idiomas es para

  1. Los programadores para expresar de manera eficiente y correcta algoritmos en una forma que las computadoras pueden usar.
  2. Los encargados de comprender los algoritmos que otros han escrito y realizar los cambios correctamente .

Las enumeraciones mejoran tanto la probabilidad de corrección como la legibilidad sin escribir mucho repetitivo. Si está dispuesto a escribir repeticiones, puede "simular" enumeraciones:

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();
}

Ahora puedes escribir:

Color trafficLightColor = Color.RED;

La repetitiva anterior tiene el mismo efecto que

public enum Color { RED, AMBER, GREEN };

Ambos proporcionan el mismo nivel de comprobación de ayuda del compilador. Boilerplate es simplemente más tipeo. Pero ahorrar mucho tipeo hace que el programador sea más eficiente (ver 1), por lo que es una característica que vale la pena.

También vale la pena por al menos una razón más:

Cambiar declaraciones

Una cosa que la static finalsimulación de enumeración anterior no le brinda son buenos switchcasos. Para los tipos de enumeración, el conmutador Java utiliza el tipo de su variable para inferir el alcance de los casos de enumeración, por lo que para lo enum Coloranterior simplemente necesita decir:

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

Tenga en cuenta que no está Color.REDen los casos. Si no usa enum, la única forma de usar cantidades con nombre switches algo como:

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

Pero ahora una variable para contener un color debe tener tipo int. El buen compilador comprobando la enumeración y elstatic final simulación se ha ido. No feliz.

Un compromiso es usar un miembro de valor escalar en la simulación:

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);
}

Ahora:

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

Pero tenga en cuenta, ¡aún más repetitivo!

Usando una enumeración como un singleton

En la plantilla anterior puede ver por qué una enumeración proporciona una forma de implementar un singleton. En lugar de escribir:

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

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

y luego accediendo con

SingletonClass.INSTANCE

solo podemos decir

public enum SingletonClass {
    INSTANCE;

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

lo que nos da lo mismo. Podemos evitar esto porque las enumeraciones de Java se implementan como clases completas con solo un poco de azúcar sintáctica esparcida por la parte superior. Esto es de nuevo menos repetitivo, pero no es obvio a menos que el idioma te sea familiar. También me gusta el hecho de que se obtiene de las diversas funciones de enumeración a pesar de que no tienen mucho sentido para el singleton: ordy values, etc (De hecho, hay una simulación más complicado cuando Color extends Integerque trabajará con el interruptor, pero es tan complicado que sea aún más muestra claramente por quéenum es una mejor idea).

Hilo de seguridad

La seguridad de los hilos es un problema potencial solo cuando los singletons se crean perezosamente sin bloqueo.

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
}

Si muchos hilos llaman getInstancesimultáneamente mientras INSTANCEtodavía es nulo, se puede crear cualquier número de instancias. Esto es malo. La única solución es agregar synchronizedacceso para proteger la variable INSTANCE.

Sin embargo, el static finalcódigo anterior no tiene este problema. Crea la instancia con entusiasmo en el tiempo de carga de la clase. La carga de clases está sincronizada.

El enumsingleton es efectivamente perezoso porque no se inicializa hasta el primer uso. La inicialización de Java también está sincronizada, por lo que varios subprocesos no pueden inicializar más de una instancia de INSTANCE. Estás obteniendo un singleton perezosamente inicializado con muy poco código. Lo único negativo es la sintaxis bastante oscura. Necesitas conocer el idioma o comprender a fondo cómo funciona la carga de clases y la inicialización para saber qué está sucediendo.

Gene
fuente
15
Ese último párrafo realmente aclaró la situación de singleton para mí. ¡Gracias! Cualquier lector que esté hojeando debería releer eso.
Basil Bourque
Estaba leyendo esto, stackoverflow.com/questions/16771373/… . Ahora estoy confundido con tu último párrafo. ¿Cómo enum no proporciona la función de inicialización laica?
Deepankar Singh
static finallos campos se inicializan en el momento de inicialización de la clase , no en el tiempo de carga. Es exactamente lo mismo que con la enuminicialización constante (de hecho, son idénticos bajo el capó). Es por eso que tratar de implementar un código de inicialización "inteligente" para perezosos siempre fue inútil, incluso en la primera versión de Java.
Holger
42

Además de los casos de uso ya mencionados, a menudo encuentro enums útiles para implementar el patrón de estrategia, siguiendo algunas pautas básicas de OOP:

  1. Tener el código donde están los datos (es decir, dentro de la enumeración en sí, o a menudo dentro de las constantes de enumeración, que pueden anular los métodos).
  2. Implementar una interfaz (o más) para no vincular el código del cliente a la enumeración (que solo debería proporcionar un conjunto de implementaciones predeterminadas).

El ejemplo más simple sería un conjunto de Comparatorimplementaciones:

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());
        }
    };
}

Este "patrón" puede usarse en escenarios mucho más complejos, haciendo un uso extensivo de todos los beneficios que vienen con la enumeración: iterar sobre las instancias, confiar en su orden implícito, recuperar una instancia por su nombre, métodos estáticos que proporcionan la instancia correcta para contextos específicos, etc. Y aún tiene todo esto oculto detrás de la interfaz para que su código funcione con implementaciones personalizadas sin modificación en caso de que desee algo que no esté disponible entre las "opciones predeterminadas".

He visto que esto se aplicó con éxito para modelar el concepto de granularidad de tiempo (diario, semanal, etc.) donde toda la lógica se encapsulaba en una enumeración (elegir la granularidad correcta para un rango de tiempo dado, el comportamiento específico vinculado a cada granularidad como constante métodos, etc.). Y aún así, Granularitysegún lo visto por la capa de servicio era simplemente una interfaz.

Costi Ciudatu
fuente
2
También puedes agregar CASE_INSENSITIVE { @Override public int compare(String s1, String s2) { return s1.compareToIgnoreCase(s2); }. Una ventaja que aún no se menciona es que obtienes un sólido soporte de serialización; el formulario persistente solo contiene el nombre de la clase y el nombre constante, sin depender de los detalles de implementación de sus comparadores.
Holger
32

Algo que ninguna de las otras respuestas ha cubierto que hace que las enumeraciones sean particularmente poderosas es la capacidad de tener métodos de plantilla . Los métodos pueden ser parte de la enumeración base y ser anulados por cada tipo. Y, con el comportamiento adjunto a la enumeración, a menudo elimina la necesidad de construcciones if-else o declaraciones de cambio como lo demuestra esta publicación de blog : ¿dónde enum.method()se ejecuta lo que originalmente se ejecutaría dentro del condicional? El mismo ejemplo también muestra el uso de importaciones estáticas con enumeraciones y produce un código similar a DSL mucho más limpio.

Algunas otras cualidades interesantes incluyen el hecho de que las enumeraciones proporcionan la implementación de equals(), toString()y hashCode()e implementar Serializabley Comparable.

Para un resumen completo de todo lo que las enumeraciones tienen para ofrecer, recomiendo la cuarta edición de Thinking in Java de Bruce Eckel, que dedica un capítulo completo al tema. Particularmente ilustrativos son los ejemplos que involucran un juego de Rock, Paper, Scissors (es decir, RoShamBo) como enumeraciones.

semillas de naranja
fuente
23

De Java documentos -

Debe usar tipos de enumeración cada vez que necesite representar un conjunto fijo de constantes. Eso incluye tipos de enumeración natural, como los planetas de nuestro sistema solar y conjuntos de datos donde conoce todos los valores posibles en el momento de la compilación, por ejemplo, las opciones en un menú, indicadores de línea de comando, etc.

Un ejemplo común es reemplazar una clase con un conjunto de constantes int finales estáticas privadas (dentro de un número razonable de constantes) con un tipo de enumeración. Básicamente, si crees que conoces todos los valores posibles de "algo" en tiempo de compilación, puedes representarlo como un tipo de enumeración. Las enumeraciones proporcionan legibilidad y flexibilidad sobre una clase con constantes.

Pocas otras ventajas que puedo pensar en tipos de enumeración. Siempre es una instancia de una clase de enumeración particular (de ahí el concepto de utilizar enumeraciones como singleton llega). Otra ventaja es que puede usar enumeraciones como un tipo en la declaración de cambio de caso. También puede usar toString () en la enumeración para imprimirlos como cadenas legibles.

Frijoles
fuente
8
¿Usaría una enumeración durante los 366 días del año? Es un conjunto fijo (366) de constantes (los días no cambian). Entonces esto sugiere que deberías. : - / Restringiría el tamaño del conjunto fijo.
moinudin
2
@marcog Con un poco de pensamiento inteligente, podría ser posible resumir días de una semana y días de cada mes en una enumeración compacta.
James P.
1
Hablando de días de la semana ... DayOfWeekenum ahora está predefinido, integrado en Java 8 y posterior como parte del marco java.time (y portado a Java 6 y 7 y a Android ).
Basil Bourque
19

Ahora, ¿por qué y para qué debería usar enum en la programación diaria?

Puede usar una enumeración para representar un conjunto fijo de constantes más bien pequeño o un modo de clase interna mientras aumenta la legibilidad. Además, Enums puede imponer una cierta rigidez cuando se usa en los parámetros del método. Ofrecen la posibilidad interesante de pasar información a un constructor como en el ejemplo de Planetas en el sitio de Oracle y, como descubrió, también permiten una forma sencilla de crear un patrón singleton.

ej .: Locale.setDefault(Locale.US)lee mejor Locale.setDefault(1)y exige el uso del conjunto fijo de valores que se muestran en un IDE cuando agrega el .separador en lugar de todos los enteros.

James P.
fuente
@arnt También arreglé la gramática en la pregunta. Gracias.
James P.
13

Enums enumerar un conjunto fijo de valores, de forma autodocumentada.
Hacen que su código sea más explícito y también menos propenso a errores.

¿Por qué no usar String, o int, en lugar de Enum, constantes?

  1. El compilador no permitirá errores tipográficos , ni valores fuera del conjunto fijo, ya que las enumeraciones son tipos en sí mismos. Consecuencias:
    • No tendrá que escribir una precondición (o un manual if) para asegurarse de que su argumento esté en el rango válido.
    • El tipo invariante viene gratis.
  2. Las enumeraciones pueden tener comportamiento, como cualquier otra clase.
  3. Probablemente necesitará una cantidad similar de memoria para usar Strings, de todos modos (esto depende de la complejidad del Enum).

Además, cada una de las Enuminstancias es una clase, para la cual puede definir su comportamiento individual.

Además, garantizan la seguridad de los subprocesos al crear las instancias (cuando se carga la enumeración), lo que ha sido de gran utilidad para simplificar el patrón Singleton .

Este blog ilustra algunas de sus aplicaciones, como una máquina de estado para un analizador.

afsantos
fuente
13

Es útil saber que enumsson como las otras clases con Constantcampos y a private constructor.

Por ejemplo,

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

El compilador lo compila de la siguiente manera;

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...
}
Indefinidamente
fuente
12

enumsignifica enumeración, es decir, mencionar (varias cosas) una por una.

Una enumeración es un tipo de datos que contiene un conjunto fijo de constantes.

O

Un enumes como un class, con un conjunto fijo de instancias conocidas en tiempo de compilación.

Por ejemplo:

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());
        }

    }
}

Ventajas de enum:

  • enum mejora la seguridad de tipo en la verificación en tiempo de compilación para evitar errores en tiempo de ejecución.
  • enum se puede usar fácilmente en el interruptor
  • enum puede ser atravesado
  • enum puede tener campos, constructores y métodos
  • enum puede implementar muchas interfaces pero no puede extender ninguna clase porque internamente extiende la clase Enum

por mas

Premraj
fuente
9

¿Qué es una enumeración?

  • enum es una palabra clave definida para enumerar un nuevo tipo de datos. Las enumeraciones de typesafe deben usarse libremente. En particular, son una alternativa robusta a las cadenas simples o constantes int utilizadas en API mucho más antiguas para representar conjuntos de elementos relacionados.

Por qué usar enum

  • las enumeraciones son implícitamente subclases finales de java.lang.Enum
  • si una enumeración es miembro de una clase, es implícitamente estática
  • new nunca se puede usar con una enumeración, incluso dentro del tipo de enumeración en sí
  • name and valueOf simplemente use el texto de las constantes enum, mientras que toString puede ser anulado para proporcionar cualquier contenido, si lo desea
  • para constantes enum, igual y == equivalen a la misma cosa, y se pueden usar indistintamente
  • las constantes enum son implícitamente públicas estáticas finales

Nota

  • las enumeraciones no pueden extender ninguna clase.
  • Una enumeración no puede ser una superclase.
  • El orden de aparición de las constantes enum se denomina "orden natural" y define el orden utilizado por otros elementos también: compareTo, orden de iteración de valores, EnumSet, EnumSet.range.
  • Una enumeración puede tener constructores, bloques estáticos y de instancia, variables y métodos, pero no puede tener métodos abstractos.
tinker_fairy
fuente
44
No explicas por qué usar enumeraciones. Simplemente enumera varias propiedades de enumeraciones en encabezados no relacionados.
Duncan Jones
@DuncanJones ¿los términos final, estático, dan el propósito de usar enumeraciones?
tinker_fairy
8

Aparte de todo lo dicho por otros. En un proyecto anterior para el que solía trabajar, mucha comunicación entre entidades (aplicaciones independientes) estaba usando números enteros que representaban un pequeño conjunto. Fue útil declarar el conjunto como enumcon métodos estáticos para obtener enumobjetos valuey viceversa. El código parecía más limpio, usabilidad de mayúsculas y minúsculas y escritura más fácil en los registros.

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;
    }
}

Crear enumobjeto a partir de valores recibidos (por ejemplo, 1,2)ProtocolType.fromInt(2) Escribir en registros usandomyEnumObj.name

Espero que esto ayude.

sErVerdevIL
fuente
6

Enum hereda todos los métodos de Objectclase y clase abstracta Enum. Por lo tanto, puede usar sus métodos de reflexión, subprocesamiento múltiple, serilización, comparables, etc. Si solo declara una constante estática en lugar de Enum, no puede. Además de eso, el valor de Enum también se puede pasar a la capa DAO.

Aquí hay un programa de ejemplo para demostrar.

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;
        }
    }
}
abishkar bhattarai
fuente
4

ENum significa "Tipo enumerado". Es un tipo de datos que tiene un conjunto fijo de constantes que usted define.

Steve
fuente
No has explicado por qué usar una enumeración.
Duncan Jones
44
Sí, lo hice. Lo usa para almacenar un conjunto fijo de constantes que usted mismo define. La aplicación específica de esto depende de usted. No hay tal cosa como decir cuándo, por qué o cómo usar algo. Eso depende de las necesidades del desarrollador. Todo lo que necesita entender es qué es y cómo funciona.
Steve
4

En mi opinión, todas las respuestas que obtuviste hasta ahora son válidas, pero en mi experiencia, lo expresaría en pocas palabras:

Use enumeraciones si desea que el compilador verifique la validez del valor de un identificador.

De lo contrario, puede usar cadenas como siempre lo hizo (probablemente definió algunas "convenciones" para su aplicación) y será muy flexible ... pero no obtendrá 100% de seguridad contra los errores tipográficos en sus cadenas y se dará cuenta solo de ellas en tiempo de ejecución.

Rafa
fuente
3

Use enumeraciones para TYPE SAFETY, esta es una función de idioma, por lo que generalmente obtendrá:

  • Soporte del compilador (vea inmediatamente los problemas de tipo)
  • Soporte de herramientas en IDEs (autocompletado en caso de cambio, casos faltantes, fuerza predeterminada, ...)
  • En algunos casos, el rendimiento de enum también es excelente ( EnumSet , alternativa de tipo seguro a los "indicadores de bit" tradicionales basados ​​en int ).

Las enumeraciones pueden tener métodos, constructores, incluso puede utilizar enumeraciones dentro de enumeraciones y combinar enumeraciones con interfaces.

Piense en las enumeraciones como tipos para reemplazar un conjunto bien definido de constantes int (que Java 'heredó' de C / C ++) y, en algunos casos, para reemplazar banderas de bits.

El libro Effective Java 2nd Edition tiene un capítulo completo sobre ellos y entra en más detalles. Consulte también esta publicación de desbordamiento de pila .

Christophe Roussy
fuente
2

Java le permite restringir la variable a tener uno de los pocos valores predefinidos; en otras palabras, un valor de una lista enumerada. El uso enumspuede ayudar a reducir los errores en su código. Aquí hay un ejemplo de enumsfuera de una clase:

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

Esto restringe coffeesizea tener ya sea: BIG, HUGEo OVERWHELMINGcomo una variable.

Rahul Prajapat
fuente
2

Enum? ¿Por qué debería ser usado? Creo que se entiende mejor cuándo lo usarás. Tengo la misma experiencia.

Supongamos que tiene una operación de creación, eliminación, edición y lectura de la base de datos.

Ahora, si crea una enumeración como una operación:

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

}

Ahora, puede declarar algo como:

private operation currentOperation;

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

Entonces puedes usarlo de muchas maneras. Siempre es bueno tener una enumeración para cosas específicas, ya que la operación de la base de datos en el ejemplo anterior se puede controlar comprobando la operación actual . Quizás se pueda decir que esto también se puede lograr con variables y valores enteros. Pero creo que Enum es más seguro y un programador.

Otra cosa: creo que todo programador ama el booleano , ¿no? Debido a que solo puede almacenar dos valores, dos valores específicos. Por lo tanto, se puede pensar que Enum tiene el mismo tipo de instalaciones donde un usuario definirá cuántos y qué tipo de valor almacenará, solo de una manera ligeramente diferente. :)

Abhishek Bhandari
fuente
1

Hasta ahora, nunca he necesitado usar enumeraciones. He estado leyendo sobre ellos desde que se introdujeron en la versión 1.5 o versión del tigre, ya que se llamaba en su día. Nunca realmente resolvieron un 'problema' para mí. Para aquellos que lo usan (y veo que muchos lo hacen), estoy seguro de que definitivamente tiene algún propósito. Solo mis 2 libras.

happybuddha
fuente
1

Lo que me dio el momento Ah-Ha fue esta comprensión: que Enum tiene un constructor privado al que solo se puede acceder mediante la enumeración pública:

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);
    }
}
djangofan
fuente
1

En cuanto a mí para que el código sea legible en el futuro, el siguiente caso de enumeración más útil se representa en el siguiente fragmento:

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;
        }
    }
};
CodeToLife
fuente
1

En mi experiencia, he visto que el uso de Enum a veces hace que los sistemas sean muy difíciles de cambiar. Si está utilizando una enumeración para un conjunto de valores específicos de dominio que cambian con frecuencia, y tiene muchas otras clases y componentes que dependen de él, es posible que desee considerar no usar un Enum.

Por ejemplo, un sistema de negociación que utiliza una Enum para mercados / intercambios. Hay muchos mercados por ahí y es casi seguro que habrá muchos subsistemas que necesitan acceder a esta lista de mercados. Cada vez que desee que se agregue un nuevo mercado a su sistema, o si desea eliminar un mercado, es posible que todo bajo el sol tenga que ser reconstruido y liberado.

Un mejor ejemplo sería algo así como un tipo de categoría de producto. Digamos que su software administra el inventario de una tienda por departamentos. Hay muchas categorías de productos y muchas razones por las que esta lista de categorías podría cambiar. Los gerentes pueden querer almacenar una nueva línea de productos, deshacerse de otras líneas de productos y posiblemente reorganizar las categorías de vez en cuando. Si tiene que reconstruir y volver a implementar todos sus sistemas simplemente porque los usuarios desean agregar una categoría de producto, entonces ha tomado algo que debería ser simple y rápido (agregar una categoría) y lo hizo muy difícil y lento.

En pocas palabras, las enumeraciones son buenas si los datos que representa son muy estáticos con el tiempo y tienen un número limitado de dependencias. Pero si los datos cambian mucho y tienen muchas dependencias, entonces necesita algo dinámico que no se verifique en el momento de la compilación (como una tabla de base de datos).

BradB
fuente
1

El singleton basado en enumeración

Una mirada moderna a un viejo problema

Este enfoque implementa el singleton aprovechando la garantía de Java de que cualquier valor enum se instancia solo una vez en un programa Java y enum proporciona soporte implícito para la seguridad de subprocesos. Dado que los valores de enumeración de Java son accesibles a nivel mundial, por lo tanto, se puede utilizar como singleton.

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

¿Como funciona esto? Bueno, la línea dos del código puede considerarse para algo como esto:

public final static Singleton SINGLETON = new Singleton(); 

Y tenemos un buen singleton inicializado temprano.

Recuerde que, dado que se trata de una enumeración, siempre puede acceder a la instancia a través de Singleton.INSTANCE :

Singleton s = Singleton.INSTANCE;
Ventajas
  • Para evitar crear otras instancias de singleton durante la deserialización, use singleton basado en enum porque JVM se encarga de la serialización de enum. La serialización y la deserialización de Enum funcionan de manera diferente que para los objetos Java normales. Lo único que se serializa es el nombre del valor enum. Durante el proceso de deserialización, la enumeraciónvalueOf método se usa con el nombre deserializado para obtener la instancia deseada.
  • Singleton basado en enumeración permite protegerse del ataque de reflexión. El tipo de enumeración en realidad extiende la Enumclase java . La razón por la que la reflexión no se puede usar para crear instancias de objetos de tipo enum es porque la especificación java no lo permite y esa regla se codifica en la implementación del newInstancemétodo de la Constructorclase, que generalmente se usa para crear objetos a través de la reflexión:
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
    throw new IllegalArgumentException("Cannot reflectively create enum objects");
  • Se supone que Enum no se debe clonar porque debe haber exactamente una instancia de cada valor.
  • El código más lacónico entre todos los singleton de realización.
Desventajas
  • El singleton basado en enumeración no permite la inicialización diferida.
  • Si cambiara su diseño y quisiera convertir su singleton a multiton, enum no lo permitiría. El patrón multitono se usa para la creación controlada de varias instancias, que se administra mediante el uso de a map. En lugar de tener una sola instancia por aplicación (p. Ej., El java.lang.Runtime), el patrón multitono garantiza una sola instancia por clave .
  • Enum solo aparece en Java 5, por lo que no puede usarlo en versiones anteriores.

Hay varias realizaciones del patrón singleton, cada una con ventajas y desventajas.

  • Ansioso por cargar singleton
  • Singleton de bloqueo doblemente verificado
  • Idioma del titular de inicialización a pedido
  • El singleton basado en enumeración

Descripción detallada de cada uno de ellos es demasiado detallado, así que acabo de poner un enlace a un buen artículo - Todo lo que quieres saber sobre Singleton

Oleg Poltoratskii
fuente
0

Usaría enumeraciones como un instrumento útil de mapeo, evitando múltiples if-else siempre que se implementen algunos métodos.

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;
    }

}

Entonces el método by(String label) permite obtener el valor Enumerado por no enumerado. Además, uno puede inventar mapeo entre 2 enumeraciones. También podría intentar '1 a muchos' o 'muchos a muchos' además de la relación predeterminada 'uno a uno'

Al final, enumes una clase Java. Por lo tanto, puede tener un mainmétodo dentro, que podría ser útil cuando necesite hacer algunas operaciones de mapeo de argsinmediato.

TEH EMPRAH
fuente
0

En lugar de hacer un montón de declaraciones constantes

Puedes agruparlos a todos en 1 enumeración

Entonces todo está organizado por el grupo común al que pertenecen

Vincent Tang
fuente
0

Las enumeraciones son como las clases. Al igual que la clase, también tiene métodos y atributos.

Las diferencias con la clase son: 1. las constantes enum son public, static, final. 2. una enumeración no puede usarse para crear un objeto y no puede extender otras clases. Pero puede implementar interfaces.

Shetu
fuente
0

Además de @BradB Answer:

Eso es tan cierto ... Es extraño que sea la única respuesta que mencione eso. Cuando los principiantes descubren enumeraciones, lo toman rápidamente como un truco de magia para verificar el identificador válido para el compilador. Y cuando el código está destinado a ser utilizado en sistemas distribuidos, lloran ... un mes después. Mantener la compatibilidad con versiones anteriores que contenga una lista no estática de valores es una preocupación real y dolorosa. Esto se debe a que cuando agrega un valor a una enumeración existente, su tipo cambia (a pesar de que el nombre no lo hace).

"Ho, espera, puede parecer del mismo tipo, ¿verdad? Después de todo, son enumeraciones con el mismo nombre, ¿y no son enumeraciones enteras debajo del capó?" Y por estas razones, su compilador probablemente no marcará el uso de una definición del tipo en sí donde esperaba la otra. Pero, de hecho, son (en las formas más importantes) diferentes tipos. Lo más importante es que tienen diferentes dominios de datos, valores que son aceptables dado el tipo. Al agregar un valor, hemos cambiado efectivamente el tipo de la enumeración y, por lo tanto, rompemos la compatibilidad con versiones anteriores.

En conclusión: utilícelo cuando lo desee, pero, por favor, compruebe que el dominio de datos utilizado es un conjunto fijo finito, ya conocido .

Nicolas Voron
fuente