Buscar..


Introducción

Las enumeraciones de Java (declaradas usando la palabra clave enum ) son sintaxis abreviada para cantidades considerables de constantes de una sola clase.

Sintaxis

  • Enumeración [pública / protegida / privada] Enum_name {// Declarar una nueva enumeración.
  • ENUM_CONSTANT_1 [, ENUM_CONSTANT_2 ...]; // Declara las constantes de enumeración. Esta debe ser la primera línea dentro de la enumeración y debe estar separada por comas, con un punto y coma al final.
  • ENUM_CONSTANT_1 (param) [, ENUM_CONSTANT_2 (param) ...]; // Declarar constantes de enumeración con parámetros. Los tipos de parámetros deben coincidir con el constructor.
  • ENUM_CONSTANT_1 {...} [, ENUM_CONSTANT_2 {...} ...]; // Declarar constantes de enumeración con métodos sobrescritos. Esto debe hacerse si la enumeración contiene métodos abstractos; Todos estos métodos deben ser implementados.
  • ENUM_CONSTANT.name () // Devuelve una cadena con el nombre de la enumeración constante.
  • ENUM_CONSTANT.ordinal () // Devuelve el ordinal de esta constante de enumeración, su posición en su declaración enum, donde a la constante inicial se le asigna un ordinal de cero.
  • Enum_name.values ​​() // Devuelve una nueva matriz (de tipo Enum_name []) que contiene cada constante de esa enumeración cada vez que se llama.
  • Enum_name.valueOf ("ENUM_CONSTANT") // El inverso de ENUM_CONSTANT.name () - devuelve la constante de enumeración con el nombre dado.
  • Enum.valueOf (Enum_name.class, "ENUM_CONSTANT") // Un sinónimo del anterior: El inverso de ENUM_CONSTANT.name () - devuelve la enumeración constante con el nombre dado.

Observaciones

Restricciones

Las enumeraciones siempre extienden java.lang.Enum , por lo que es imposible que una enumeración extienda una clase. Sin embargo, pueden implementar muchas interfaces.

consejos y trucos

Debido a su representación especializada, hay mapas y conjuntos más eficientes que se pueden usar con las enumeraciones como sus claves. Estos a menudo se ejecutan más rápido que sus contrapartes no especializadas.

Declarar y usar una enumeración básica

Enum puede ser considerado como sintaxis de azúcar para una clase sellada que solo se crea una instancia de varias veces conocidas en tiempo de compilación para definir un conjunto de constantes.

Una enumeración simple para enumerar las diferentes temporadas se declararía de la siguiente manera:

public enum Season {
    WINTER,
    SPRING,
    SUMMER,
    FALL
}

Si bien las constantes de enumeración no necesariamente tienen que estar en mayúsculas, es una convención de Java que los nombres de las constantes están en mayúsculas, con palabras separadas por guiones bajos.


Puedes declarar un Enum en su propio archivo:

/**
 * This enum is declared in the Season.java file.
*/
public enum Season {
    WINTER,
    SPRING,
    SUMMER,
    FALL
}

Pero también puedes declararlo dentro de otra clase:

 public class Day {

    private Season season;

    public String getSeason() {
        return season.name();
    }

    public void setSeason(String season) {
        this.season = Season.valueOf(season);
    }

    /**
     * This enum is declared inside the Day.java file and 
     * cannot be accessed outside because it's declared as private.
     */
    private enum Season {
        WINTER,
        SPRING,
        SUMMER,
        FALL
    }

}

Finalmente, no puede declarar un Enum dentro de un cuerpo de método o constructor:

public class Day {

    /**
     * Constructor
    */
    public Day() {
        // Illegal. Compilation error
        enum Season {
            WINTER,
            SPRING,
            SUMMER,
            FALL
        }
    }

    public void aSimpleMethod() {
        // Legal. You can declare a primitive (or an Object) inside a method. Compile!
        int primitiveInt = 42;

        // Illegal. Compilation error.
        enum Season {
            WINTER,
            SPRING,
            SUMMER,
            FALL
        }

        Season season = Season.SPRING;
    }
    
}

No se permiten constantes de enumeración duplicadas:

public enum Season {
    WINTER,
    WINTER, //Compile Time Error : Duplicate Constants
    SPRING,
    SUMMER,
    FALL
} 

Cada constante de enumeración es public , static y final por defecto. Como todas las constantes son static , se puede acceder directamente usando el nombre de enumeración.

Las constantes de enumeración se pueden pasar como parámetros del método:

public static void display(Season s) {
    System.out.println(s.name());  // name() is a built-in method that gets the exact name of the enum constant
}

display(Season.WINTER);  // Prints out "WINTER"

Puede obtener una matriz de las constantes de enumeración utilizando el método values() . Se garantiza que los valores están en orden de declaración en la matriz devuelta:

Season[] seasons = Season.values();

Nota: este método asigna una nueva matriz de valores cada vez que se llama.


Para iterar sobre las constantes de enumeración:

public static void enumIterate() {
    for (Season s : Season.values()) {
        System.out.println(s.name());
    }
}

Puede utilizar enumeraciones en una instrucción de switch :

public static void enumSwitchExample(Season s) {
    switch(s) {
        case WINTER:
            System.out.println("It's pretty cold");
            break;
        case SPRING:
            System.out.println("It's warming up");
            break;
        case SUMMER:
            System.out.println("It's pretty hot");
            break;
        case FALL:
            System.out.println("It's cooling down");
            break;
    }
}

También puedes comparar constantes de enumeración usando == :

Season.FALL == Season.WINTER    // false
Season.SPRING == Season.SPRING  // true

Otra forma de comparar las constantes de enumeración es utilizando equals() como se muestra a continuación, lo que se considera una mala práctica, ya que puede caer fácilmente en las dificultades de la siguiente manera:

Season.FALL.equals(Season.FALL); // true
Season.FALL.equals(Season.WINTER); // false
Season.FALL.equals("FALL"); // false and no compiler error

Además, aunque el conjunto de instancias en la enum no se puede cambiar en tiempo de ejecución, las instancias en sí mismas no son inherentemente inmutables porque, como cualquier otra clase, una enum puede contener campos mutables como se muestra a continuación.

public enum MutableExample {
    A,
    B;

    private int count = 0;

    public void increment() {
        count++;
    }

    public void print() {
        System.out.println("The count of " + name() + " is " + count);
    }
}

// Usage:
MutableExample.A.print();       // Outputs 0
MutableExample.A.increment();
MutableExample.A.print();       // Outputs 1 -- we've changed a field   
MutableExample.B.print();       // Outputs 0 -- another instance remains unchanged

Sin embargo, una buena práctica es hacer que las instancias de enum inmutables, es decir, cuando no tienen campos adicionales o todos estos campos están marcados como final y son inmutables. Esto asegurará que durante toda la vida de la aplicación, una enum no perderá memoria y que es seguro usar sus instancias en todos los subprocesos.


Enums implícitamente implementa Serializable y Comparable porque la clase Enum hace:

public abstract class Enum<E extends Enum<E>>
extends Object
implements Comparable<E>, Serializable

Enums con constructores

Una enum no puede tener un constructor público; sin embargo, los constructores privados son aceptables (los constructores para enums son de paquete privado por defecto):

public enum Coin {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25); // usual names for US coins
    // note that the above parentheses and the constructor arguments match
    private int value;

    Coin(int value) { 
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

int p = Coin.NICKEL.getValue(); // the int value will be 5

Se recomienda mantener todos los campos privados y proporcionar métodos de obtención, ya que hay un número finito de instancias para una enumeración.


Si tuvieras que implementar un Enum como class , se vería así:

public class Coin<T extends Coin<T>> implements Comparable<T>, Serializable{
    public static final Coin PENNY = new Coin(1);
    public static final Coin NICKEL = new Coin(5);
    public static final Coin DIME = new Coin(10);
    public static final Coin QUARTER = new Coin(25);

    private int value;

    private Coin(int value){
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

int p = Coin.NICKEL.getValue(); // the int value will be 5

Las constantes de enumeración son técnicamente mutables, por lo que se podría agregar un setter para cambiar la estructura interna de una constante de enumeración. Sin embargo, esto se considera muy mala práctica y debe evitarse.

La mejor práctica es hacer que los campos de Enum sean inmutables, con final :

public enum Coin {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25);

    private final int value;

    Coin(int value){ 
        this.value = value;
    }

    ...

}

Puede definir múltiples constructores en la misma enumeración. Cuando lo hace, los argumentos que pasa en su declaración de enumeración deciden a qué constructor se llama:

public enum Coin {
    PENNY(1, true), NICKEL(5, false), DIME(10), QUARTER(25);

    private final int value;
    private final boolean isCopperColored;

    Coin(int value){
        this(value, false);
    }

    Coin(int value, boolean isCopperColored){ 
        this.value = value;
        this.isCopperColored = isCopperColored;
    }

    ...

}

Nota: Todos los campos de enumeración no primitivos deberían implementar Serializable porque la clase Enum sí lo hace.

Utilizando métodos y bloques estáticos.

Una enumeración puede contener un método, al igual que cualquier clase. Para ver cómo funciona esto, declararemos una enumeración como esta:

public enum Direction {
    NORTH, SOUTH, EAST, WEST;
}

Tengamos un método que devuelva la enumeración en la dirección opuesta:

public enum Direction {
    NORTH, SOUTH, EAST, WEST;

    public Direction getOpposite(){
        switch (this){
            case NORTH:
                return SOUTH;               
            case SOUTH:
                return NORTH;                
            case WEST:
                return EAST; 
            case EAST:
                return WEST;  
            default: //This will never happen
                return null;
        }
    }
}

Esto se puede mejorar aún más mediante el uso de campos y bloques de inicialización estáticos:

public enum Direction {
    NORTH, SOUTH, EAST, WEST;
    
    private Direction opposite;
    
    public Direction getOpposite(){
        return opposite;
    }
    
    static {
        NORTH.opposite = SOUTH;
        SOUTH.opposite = NORTH;
        WEST.opposite = EAST;
        EAST.opposite = WEST;
    }
}

En este ejemplo, la dirección opuesta se almacena en un campo de instancia privada opposite , que se inicializa de forma estática la primera vez que se utiliza una Direction . En este caso particular (debido a que el NORTH referencia al SOUTH y viceversa), no podemos usar Enums con constructores aquí (los Constructores NORTH(SOUTH), SOUTH(NORTH), EAST(WEST), WEST(EAST) serían más elegantes y permitirían opposite a ser declarado final , pero sería auto-referencial y por lo tanto no está permitido).

Implementa interfaz

Esta es una enum que también es una función invocable que prueba las entradas de String contra patrones de expresión regular precompilados.

import java.util.function.Predicate;
import java.util.regex.Pattern;

enum RegEx implements Predicate<String> {
    UPPER("[A-Z]+"), LOWER("[a-z]+"), NUMERIC("[+-]?[0-9]+");

    private final Pattern pattern;

    private RegEx(final String pattern) {
        this.pattern = Pattern.compile(pattern);
    }

    @Override 
    public boolean test(final String input) {
        return this.pattern.matcher(input).matches();
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(RegEx.UPPER.test("ABC"));
        System.out.println(RegEx.LOWER.test("abc"));
        System.out.println(RegEx.NUMERIC.test("+111"));
    }
}

Cada miembro de la enumeración también puede implementar el método:

import java.util.function.Predicate;

enum Acceptor implements Predicate<String> {
    NULL {
        @Override
        public boolean test(String s) { return s == null; }
    },
    EMPTY {
        @Override
        public boolean test(String s) { return s.equals(""); }
    },
    NULL_OR_EMPTY {
        @Override
        public boolean test(String s) { return NULL.test(s) || EMPTY.test(s); }
    };
}

public class Main {
    public static void main(String[] args) {
        System.out.println(Acceptor.NULL.test(null));  // true
        System.out.println(Acceptor.EMPTY.test(""));   // true
        System.out.println(Acceptor.NULL_OR_EMPTY.test(" ")); // false
    }
}

Patrón de polimorfismo enum

Cuando un método necesita aceptar un conjunto "extensible" de valores de enum , el programador puede aplicar polimorfismo como en una class normal creando una interfaz que se usará en cualquier lugar donde se usen las enum :

public interface ExtensibleEnum {
    String name();
}

De esta manera, cualquier enum etiquetada por (implementando) la interfaz se puede usar como un parámetro, lo que permite al programador crear una cantidad variable de enum que será aceptada por el método. Esto puede ser útil, por ejemplo, en las API donde hay una enum predeterminada (no modificable) y el usuario de estas API desea "extender" la enum con más valores.

Un conjunto de valores de enumeración predeterminados se puede definir de la siguiente manera:

public enum DefaultValues implements ExtensibleEnum {
    VALUE_ONE, VALUE_TWO;
}

Los valores adicionales se pueden definir así:

public enum ExtendedValues implements ExtensibleEnum {
    VALUE_THREE, VALUE_FOUR;
}

Ejemplo que muestra cómo usar las enumeraciones: observe cómo printEnum() acepta valores de ambos tipos de enum :

private void printEnum(ExtensibleEnum val) {
    System.out.println(val.name());
}  

printEnum(DefaultValues.VALUE_ONE);    // VALUE_ONE
printEnum(DefaultValues.VALUE_TWO);    // VALUE_TWO
printEnum(ExtendedValues.VALUE_THREE); // VALUE_THREE
printEnum(ExtendedValues.VALUE_FOUR);  // VALUE_FOUR

Nota: este patrón no le impide redefinir los valores de enumeración, que ya están definidos en una enumeración, en otra enumeración. Estos valores de enumeración serían diferentes instancias entonces. Además, no es posible utilizar switch-on-enum ya que todo lo que tenemos es la interfaz, no la enum real.

Enums con métodos abstractos

Las enumeraciones pueden definir métodos abstractos, que cada miembro de la enum debe implementar.

enum Action {
    DODGE {
        public boolean execute(Player player) {
            return player.isAttacking();
        }
    },
    ATTACK {
        public boolean execute(Player player) {
            return player.hasWeapon();
        }
    },
    JUMP {
        public boolean execute(Player player) {
            return player.getCoordinates().equals(new Coordinates(0, 0));
        }
    };

    public abstract boolean execute(Player player);
}

Esto permite que cada miembro de la enumeración defina su propio comportamiento para una operación dada, sin tener que activar tipos en un método en la definición de nivel superior.

Tenga en cuenta que este patrón es una forma corta de lo que normalmente se logra utilizando polimorfismo y / o implementación de interfaces.

Documentando enumeraciones

No siempre el nombre de la enum es lo suficientemente claro como para ser entendido. Para documentar una enum , use javadoc estándar:

/**
 * United States coins
 */
public enum Coins {
    
    /**
     * One-cent coin, commonly known as a penny, 
     * is a unit of currency equaling one-hundredth 
     * of a United States dollar
     */
    PENNY(1),

    /**
     * A nickel is a five-cent coin equaling 
     * five-hundredth of a United States dollar
     */        
    NICKEL(5),

    /**
     * The dime is a ten-cent coin refers to 
     * one tenth of a United States dollar
     */        
    DIME(10),

    /**
     * The quarter is a US coin worth 25 cents, 
     * one-fourth of a United States dollar
     */        
    QUARTER(25);

    private int value;

    Coins(int value){ 
        this.value = value;
    }

    public int getValue(){
        return value;
    }
}

Obtener los valores de una enumeración

Cada clase de enumeración contiene un método estático implícito llamado values() . Este método devuelve una matriz que contiene todos los valores de esa enumeración. Puede utilizar este método para iterar sobre los valores. Sin embargo, es importante tener en cuenta que este método devuelve una nueva matriz cada vez que se llama.

public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
    
    /**
    * Print out all the values in this enum.
    */
    public static void printAllDays() {
        for(Day day : Day.values()) {
            System.out.println(day.name());
        }
    }
}

Si necesita un Set también puede usar EnumSet.allOf(Day.class) .

Enum como un parámetro de tipo limitado

Al escribir una clase con genéricos en java, es posible asegurarse de que el parámetro type sea una enumeración. Como todas las enumeraciones amplían la clase Enum , se puede usar la siguiente sintaxis.

public class Holder<T extends Enum<T>> {
    public final T value;

    public Holder(T init) {
        this.value = init;
    }
}

En este ejemplo, el tipo T debe ser una enumeración.

Obtener enumeración constante por nombre

Digamos que tenemos una enumeración DayOfWeek :

enum DayOfWeek {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;
}

Una enumeración se compila con un método static valueOf() incorporado que se puede usar para buscar una constante por su nombre:

String dayName = DayOfWeek.SUNDAY.name();
assert dayName.equals("SUNDAY");

DayOfWeek day = DayOfWeek.valueOf(dayName);
assert day == DayOfWeek.SUNDAY;

Esto también es posible utilizando un tipo de enumeración dinámica:

Class<DayOfWeek> enumType = DayOfWeek.class;
DayOfWeek day = Enum.valueOf(enumType, "SUNDAY");
assert day == DayOfWeek.SUNDAY;

Ambos de estos métodos valueOf() lanzarán una IllegalArgumentException si la enumeración especificada no tiene una constante con un nombre coincidente.

La biblioteca de Guava proporciona un método auxiliar Enums.getIfPresent() que devuelve un Guava Optional para eliminar el manejo de excepciones explícitas:

DayOfWeek defaultDay = DayOfWeek.SUNDAY;
DayOfWeek day = Enums.valueOf(DayOfWeek.class, "INVALID").or(defaultDay);
assert day == DayOfWeek.SUNDAY;

Implementar el patrón Singleton con una enumeración de un solo elemento.

Las constantes de enumeración se crean instancias cuando se hace referencia a una enumeración por primera vez. Por lo tanto, eso permite implementar el patrón de diseño del software Singleton con una enumeración de un solo elemento.

public enum Attendant {

    INSTANCE;

    private Attendant() {
        // perform some initialization routine
    }

    public void sayHello() {
        System.out.println("Hello!");
    }
}


public class Main {

    public static void main(String... args) {
        Attendant.INSTANCE.sayHello();// instantiated at this point
    }
}

Según el libro "Effective Java" de Joshua Bloch, una enumeración de un solo elemento es la mejor manera de implementar un singleton. Este enfoque tiene las siguientes ventajas:

  • seguridad del hilo
  • garantía de instanciación única
  • serialización fuera de la caja

Y como se muestra en la sección implementa la interfaz, este singleton también puede implementar una o más interfaces.

Enumerar con propiedades (campos)

En caso de que queramos usar enum con más información y no solo valores constantes, queremos poder comparar dos enumeraciones.

Considere el siguiente ejemplo:

public enum Coin {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25);

    private final int value;

    Coin(int value){
        this.value = value;
    }

    public boolean isGreaterThan(Coin other){
        return this.value > other.value;
    }

}

Aquí definimos un Enum llamado Coin que representa su valor. Con el método isGreaterThan podemos comparar dos enum s:

Coin penny = Coin.PENNY;
Coin dime = Coin.DIME;

System.out.println(penny.isGreaterThan(dime)); // prints: false
System.out.println(dime.isGreaterThan(penny)); // prints: true

Convertir enum a cadena

A veces quieres convertir tu enumeración en una Cadena, hay dos formas de hacerlo.

Supongamos que tenemos:

public enum Fruit {
    APPLE, ORANGE, STRAWBERRY, BANANA, LEMON, GRAPE_FRUIT;
}

Entonces, ¿cómo convertimos algo como Fruit.APPLE a "APPLE" ?


Convertir usando name()

name() es un método interno en enum que devuelve la representación de String de la enumeración, la String retorno representa exactamente cómo se definió el valor de enumeración.

Por ejemplo:

System.out.println(Fruit.BANANA.name());      // "BANANA"
System.out.println(Fruit.GRAPE_FRUIT.name()); // "GRAPE_FRUIT"

Convertir utilizando toString()

toString() está, por defecto , reemplazado para tener el mismo comportamiento que name()

Sin embargo, es probable que los desarrolladores toString() para que imprima una String más fácil de usar

No uses toString() si quieres verificar tu código, name() es mucho más estable para eso. Solo use toString() cuando vaya a dar salida al valor de logs o stdout o algo así

Por defecto:

System.out.println(Fruit.BANANA.toString());      // "BANANA"
System.out.println(Fruit.GRAPE_FRUIT.toString()); // "GRAPE_FRUIT"

Ejemplo de ser anulado

System.out.println(Fruit.BANANA.toString());      // "Banana"
System.out.println(Fruit.GRAPE_FRUIT.toString()); // "Grape Fruit"

Enumeración específica del cuerpo

En una enum es posible definir un comportamiento específico para una constante particular de la enum que anula el comportamiento predeterminado de la enum , esta técnica se conoce como cuerpo específico constante .

Supongamos que tres estudiantes de piano, John, Ben y Luke, se definen en una enum llamada PianoClass , de la siguiente manera:

    enum PianoClass {
    JOHN, BEN, LUKE;
        public String getSex() {
            return "Male";
        }
        public String getLevel() {
            return "Beginner";
        }
    }

Y un día llegan otros dos estudiantes, Rita y Tom, con un sexo (femenino) y un nivel (intermedio) que no coinciden con los anteriores:

    enum PianoClass2 {
    JOHN, BEN, LUKE, RITA, TOM;
        public String getSex() {
            return "Male"; // issue, Rita is a female
        }
        public String getLevel() {
            return "Beginner"; // issue, Tom is an intermediate student
        }
    }

de modo que simplemente agregar los nuevos alumnos a la declaración constante, como sigue, no es correcto:

PianoClass2 tom = PianoClass2.TOM;
PianoClass2 rita = PianoClass2.RITA;
System.out.println(tom.getLevel()); // prints Beginner -> wrong Tom's not a beginner
System.out.println(rita.getSex()); // prints Male -> wrong Rita's not a male

Es posible definir un comportamiento específico para cada una de las constantes, Rita y Tom, que anula el comportamiento predeterminado de PianoClass2 la siguiente manera:

enum PianoClass3 {
    JOHN, BEN, LUKE,
    RITA {
        @Override
        public String getSex() {
            return "Female";
        }
    },
    TOM {
        @Override
        public String getLevel() {
            return "Intermediate";
        }
    };
    public String getSex() {
        return "Male";
    }
    public String getLevel() {
        return "Beginner";
    }
}

y ahora el nivel de Tom y el sexo de Rita son como deberían ser:

PianoClass3 tom = PianoClass3.TOM;
PianoClass3 rita = PianoClass3.RITA;
System.out.println(tom.getLevel()); // prints Intermediate
System.out.println(rita.getSex()); // prints Female

Otra forma de definir el cuerpo específico del contenido es mediante el uso de constructor, por ejemplo:

enum Friend {
    MAT("Male"),
    JOHN("Male"),
    JANE("Female");
    
    private String gender;

    Friend(String gender) {
        this.gender = gender;
    }

    public String getGender() {
        return this.gender;
    }
}

y uso:

Friend mat = Friend.MAT;
Friend john = Friend.JOHN;
Friend jane = Friend.JANE;
System.out.println(mat.getGender());     // Male
System.out.println(john.getGender());    // Male
System.out.println(jane.getGender());    // Female

Enumeración cero instancia

enum Util {
    /* No instances */;

    public static int clamp(int min, int max, int i) {
        return Math.min(Math.max(i, min), max);
    }

    // other utility methods...
}

Del mismo modo que enum se puede utilizar para singletons (clases de 1 instancia), se puede usar para clases de utilidad (0 clases de instancia). Solo asegúrese de terminar la lista (vacía) de constantes de enumeración con un ; .

Consulte la pregunta Zero instance enum contra constructores privados para evitar la creación de instancias para una discusión sobre pros y contras en comparación con constructores privados.

Enums con campos estáticos

Si se requiere que su clase de enumeración tenga campos estáticos, tenga en cuenta que se crean después de los propios valores de enumeración. Eso significa que, el siguiente código resultará en una NullPointerException :

enum Example {
    ONE(1), TWO(2);

    static Map<String, Integer> integers = new HashMap<>();

    private Example(int value) {
        integers.put(this.name(), value);
    }
}

Una posible forma de solucionar esto:

enum Example {
    ONE(1), TWO(2);

    static Map<String, Integer> integers;

    private Example(int value) {
        putValue(this.name(), value);
    }

    private static void putValue(String name, int value) {
        if (integers == null)
            integers = new HashMap<>();
        integers.put(name, value);
    }
}

No inicialice el campo estático:

enum Example {
    ONE(1), TWO(2);

    // after initialisisation integers is null!!
    static Map<String, Integer> integers = null;

    private Example(int value) {
        putValue(this.name(), value);
    }

    private static void putValue(String name, int value) {
        if (integers == null)
            integers = new HashMap<>();
        integers.put(name, value);
    }
    // !!this may lead to null poiner exception!!
    public int getValue(){
        return (Example.integers.get(this.name()));
    }
}

inicialisis

  • crear los valores de enumeración
    • como efecto secundario putValue () llamado que inicializa enteros
  • se establecen los valores estáticos
    • enteros = nulo; // se ejecuta después de las enumeraciones por lo que el contenido de los enteros se pierde

Comparar y Contiene para los valores Enum

Enums contiene solo constantes y puede compararse directamente con == . Por lo tanto, solo se necesita una verificación de referencia, no es necesario utilizar el método .equals . Además, si .equals usa incorrectamente, puede generar la NullPointerException mientras que ese no es el caso con == check.

enum Day {
    GOOD, AVERAGE, WORST;
}

public class Test {

    public static void main(String[] args) {
        Day day = null;

        if (day.equals(Day.GOOD)) {//NullPointerException!
            System.out.println("Good Day!");
        }

        if (day == Day.GOOD) {//Always use == to compare enum
            System.out.println("Good Day!");
        }

    }
}

Para agrupar, complementar, EnumSet valores de enumeración, tenemos la clase EnumSet que contiene diferentes métodos.

  • EnumSet#range : para obtener un subconjunto de enumeración por rango definido por dos puntos finales

  • EnumSet#of : Conjunto de enumeraciones específicas sin ningún rango. Múltiples sobrecargas of métodos están ahí.

  • EnumSet#complementOf : Conjunto de enumeración que es el complemento de los valores de enumeración proporcionados en el parámetro del método

    enum Page {
       A1, A2, A3, A4, A5, A6, A7, A8, A9, A10
    }
    
    public class Test {
    
      public static void main(String[] args) {
          EnumSet<Page> range = EnumSet.range(Page.A1, Page.A5);
    
          if (range.contains(Page.A4)) {
              System.out.println("Range contains A4");
          }
    
          EnumSet<Page> of = EnumSet.of(Page.A1, Page.A5, Page.A3);
    
          if (of.contains(Page.A1)) {
              System.out.println("Of contains A1");
          }
      }
    }
    


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow