Java Language
Enums
Buscar..
Introducción
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 usetoString()
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 finalesEnumSet#of
: Conjunto de enumeraciones específicas sin ningún rango. Múltiples sobrecargasof
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étodoenum 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"); } } }