Java
Tutorial Java: Enumeraciones Enums
Java Enumeraciones: Aprende cómo las enums mejoran la legibilidad y seguridad del código en Java mediante ejemplos prácticos y patrones de diseño.
Aprende Java y certifícateDefinición y sintaxis básica
Las enumeraciones (enums) en Java son un tipo especial de clase que permite definir un conjunto fijo de constantes con nombre.
La sintaxis básica para declarar una enumeración es:
public enum DiaSemana {
LUNES,
MARTES,
MIERCOLES,
JUEVES,
VIERNES,
SABADO,
DOMINGO
}
Cada valor dentro del enum (LUNES
, MARTES
, etc.) se denomina constante enum y representa una instancia única e inmutable de ese tipo. Por convención, estas constantes se nombran en mayúsculas, siguiendo el estilo de las constantes tradicionales.
Para utilizar un enum, se accede directamente a sus constantes a través del nombre del tipo:
// Declarar una variable de tipo enum
DiaSemana hoy = DiaSemana.LUNES;
// Comparación segura de tipos
if (hoy == DiaSemana.VIERNES) {
System.out.println("¡Por fin es viernes!");
}
Las enumeraciones funcionan muy bien con las estructuras de control switch:
switch (hoy) {
case LUNES:
System.out.println("Inicio de semana");
break;
case VIERNES:
System.out.println("Fin de semana laboral");
break;
case SABADO, DOMINGO: // Múltiples casos en la sintaxis moderna
System.out.println("Fin de semana");
break;
default:
System.out.println("Día entre semana");
}
Cada constante enum es un objeto único, lo que permite compararlas con el operador ==
en lugar de .equals()
.
Todos los enums extienden implícitamente la clase java.lang.Enum
, que proporciona algunos métodos:
// Obtener todas las constantes como array
DiaSemana[] todos = DiaSemana.values();
// Recorrer todos los valores
for (DiaSemana dia : DiaSemana.values()) {
System.out.println(dia);
}
// Convertir una cadena a constante enum
DiaSemana dia = DiaSemana.valueOf("LUNES"); // Debe coincidir exactamente
// Obtener el nombre como cadena
String nombre = DiaSemana.LUNES.name(); // "LUNES"
// Obtener la posición ordinal (base 0)
int posicion = DiaSemana.MIERCOLES.ordinal(); // 2
El método valueOf()
lanza una excepción IllegalArgumentException
si la cadena proporcionada no coincide exactamente con el nombre de una constante enum, incluyendo el uso de mayúsculas.
Las enumeraciones proporcionan seguridad de tipos (type-safety), lo que significa que el compilador verifica que solo se utilicen constantes válidas del tipo enum correspondiente, evitando errores que podrían ocurrir al usar constantes basadas en enteros o cadenas.
Métodos y constructores en enumeraciones
Las enumeraciones en Java son más que simples listas de constantes. Son clases completas que pueden tener constructores, campos y métodos.
Constructores en enumeraciones
Los constructores en enums son siempre implícitamente privados, incluso si no se especifica el modificador private
.
Un constructor de enum se utiliza para inicializar cada constante con valores específicos:
public enum Mes {
ENERO(31),
FEBRERO(28), // En año no bisiesto
MARZO(31),
ABRIL(30),
MAYO(31),
JUNIO(30),
JULIO(31),
AGOSTO(31),
SEPTIEMBRE(30),
OCTUBRE(31),
NOVIEMBRE(30),
DICIEMBRE(31);
private final int dias;
// Constructor para inicializar cada constante
Mes(int dias) {
this.dias = dias;
}
// Método getter para acceder al campo
public int getDias() {
return dias;
}
}
En este ejemplo, cada constante del enum Mes
tiene un valor asociado que representa la cantidad de días en ese mes. Este valor se inicializa a través del constructor cuando se define cada constante.
Para usar este enum con sus valores asociados:
// Obtener los días de un mes específico
int diasEnero = Mes.ENERO.getDias(); // 31
System.out.println("Febrero tiene " + Mes.FEBRERO.getDias() + " días");
// Encontrar meses con 31 días
for (Mes mes : Mes.values()) {
if (mes.getDias() == 31) {
System.out.println(mes + " tiene 31 días");
}
}
Métodos en enumeraciones
Además de los métodos heredados de la clase Enum
, se pueden definir métodos propios:
public enum Operacion {
SUMA, RESTA, MULTIPLICACION, DIVISION;
// Método que implementa la operación correspondiente
public double ejecutar(double x, double y) {
return switch (this) {
case SUMA -> x + y;
case RESTA -> x - y;
case MULTIPLICACION -> x * y;
case DIVISION -> {
if (y == 0) {
throw new ArithmeticException("División por cero");
}
yield x / y;
}
};
}
}
Este enum se puede utilizar para realizar operaciones matemáticas:
double resultado = Operacion.SUMA.ejecutar(5, 3); // 8.0
System.out.println(Operacion.DIVISION.ejecutar(10, 2)); // 5.0
También se pueden agregar métodos estáticos a los enums, lo que puede ser útil para operaciones que involucran a varias constantes:
public enum Color {
ROJO(255, 0, 0),
VERDE(0, 255, 0),
AZUL(0, 0, 255);
private final int r;
private final int g;
private final int b;
Color(int r, int g, int b) {
this.r = r;
this.g = g;
this.b = b;
}
public int getR() { return r; }
public int getG() { return g; }
public int getB() { return b; }
// Calcular el brillo del color (fórmula simplificada)
public int getBrillo() {
return (r + g + b) / 3;
}
// Método estático para encontrar el color más brillante
public static Color masClaro(Color c1, Color c2) {
return c1.getBrillo() > c2.getBrillo() ? c1 : c2;
}
}
Es posible sobreescribir los métodos heredados de Enum
o Object
:
public enum EstadoTarea {
PENDIENTE, EN_PROGRESO, COMPLETADA, CANCELADA;
@Override
public String toString() {
// Convertir de "PENDIENTE" a "Pendiente" para mejor presentación
return name().charAt(0) + name().substring(1).toLowerCase().replace('_', ' ');
}
}
Este código personaliza cómo se representan las constantes enum como cadenas:
System.out.println(EstadoTarea.EN_PROGRESO); // "En progreso" en lugar de "EN_PROGRESO"
Enums con campos y comportamiento personalizado
Enums con campos personalizados
Cada constante enum puede tener sus propios valores para uno o más campos, inicializados a través del constructor:
public enum TamañoCafe {
PEQUEÑO(250, 2.5),
MEDIANO(350, 3.0),
GRANDE(450, 3.5),
EXTRA_GRANDE(550, 4.0);
private final int mililitros;
private final double precio;
TamañoCafe(int mililitros, double precio) {
this.mililitros = mililitros;
this.precio = precio;
}
public int getMililitros() {
return mililitros;
}
public double getPrecio() {
return precio;
}
// Método para calcular el precio por mililitro
public double getPrecioPorML() {
return precio / mililitros;
}
@Override
public String toString() {
return name() + " (" + mililitros + "ml, €" + precio + ")";
}
}
Este enum asocia cada tamaño de café con su volumen en mililitros y su precio, y proporciona métodos para acceder a estos valores y realizar cálculos.
Se puede utilizar así:
TamañoCafe miCafe = TamañoCafe.GRANDE;
System.out.println("Mi café es " + miCafe); // "GRANDE (450ml, €3.5)"
System.out.println("Precio por ml: " + miCafe.getPrecioPorML() + "€");
// Encontrar el tamaño con mejor relación calidad-precio
TamañoCafe mejorValor = TamañoCafe.PEQUEÑO;
for (TamañoCafe tamaño : TamañoCafe.values()) {
if (tamaño.getPrecioPorML() < mejorValor.getPrecioPorML()) {
mejorValor = tamaño;
}
}
System.out.println("Mejor valor: " + mejorValor);
Enums con comportamiento específico por constante
Cada constante de un enum puede implementar métodos de manera diferente. Esto se logra haciendo que el método sea abstracto en el enum y proporcionando implementaciones específicas para cada constante:
public enum Operacion {
SUMA {
@Override
public double ejecutar(double x, double y) {
return x + y;
}
@Override
public String getSimbolo() {
return "+";
}
},
RESTA {
@Override
public double ejecutar(double x, double y) {
return x - y;
}
@Override
public String getSimbolo() {
return "-";
}
},
MULTIPLICACION {
@Override
public double ejecutar(double x, double y) {
return x * y;
}
@Override
public String getSimbolo() {
return "*";
}
},
DIVISION {
@Override
public double ejecutar(double x, double y) {
if (y == 0) {
throw new ArithmeticException("División por cero");
}
return x / y;
}
@Override
public String getSimbolo() {
return "/";
}
};
// Método abstracto que cada constante debe implementar
public abstract double ejecutar(double x, double y);
// Método abstracto para obtener el símbolo de la operación
public abstract String getSimbolo();
// Método común para todas las constantes
public String describir() {
return "Operación " + name().toLowerCase() + " (" + getSimbolo() + ")";
}
}
Cada constante del enum Operacion
proporciona su propia implementación de los métodos abstractos ejecutar
y getSimbolo
, mientras que todas comparten el método describir
.
Se puede utilizar así:
for (Operacion op : Operacion.values()) {
System.out.println(op.describir());
System.out.println("5 " + op.getSimbolo() + " 3 = " + op.ejecutar(5, 3));
}
Implementación de interfaces en enums
Los enums también pueden implementar interfaces:
public interface Descriptor {
String describe();
String getCategoria();
}
public enum TipoVehiculo implements Descriptor {
COCHE("Vehículo de cuatro ruedas para transporte de personas", "Terrestre"),
MOTO("Vehículo de dos ruedas", "Terrestre"),
BARCO("Vehículo para navegar en agua", "Acuático"),
AVION("Vehículo para volar", "Aéreo");
private final String descripcion;
private final String categoria;
TipoVehiculo(String descripcion, String categoria) {
this.descripcion = descripcion;
this.categoria = categoria;
}
@Override
public String describe() {
return descripcion;
}
@Override
public String getCategoria() {
return categoria;
}
}
Se puede utilizar así:
// Usar el enum como implementación de la interfaz
Descriptor desc = TipoVehiculo.BARCO;
System.out.println(desc.describe());
System.out.println("Categoría: " + desc.getCategoria());
// Filtrar vehículos por categoría
for (TipoVehiculo tipo : TipoVehiculo.values()) {
if (tipo.getCategoria().equals("Terrestre")) {
System.out.println(tipo + ": " + tipo.describe());
}
}
Patrones de diseño con enumeraciones
Singleton Pattern
Cada constante enum es, por naturaleza, un singleton (instancia única). Esto convierte a los enums en una buena forma de implementar el patrón Singleton:
public enum DatabaseConnection {
INSTANCE;
private Connection connection;
// El constructor se llama solo una vez para INSTANCE
DatabaseConnection() {
try {
// Configurar la conexión a la base de datos
connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb", "user", "password");
System.out.println("Conexión a la base de datos establecida");
} catch (SQLException e) {
throw new RuntimeException("Error al conectar a la base de datos", e);
}
}
public Connection getConnection() {
return connection;
}
public ResultSet executeQuery(String sql) throws SQLException {
Statement stmt = connection.createStatement();
return stmt.executeQuery(sql);
}
public void closeConnection() {
if (connection != null) {
try {
connection.close();
System.out.println("Conexión a la base de datos cerrada");
} catch (SQLException e) {
System.err.println("Error al cerrar la conexión: " + e.getMessage());
}
}
}
}
Esta implementación proporciona una conexión a base de datos singleton, que se puede utilizar en toda la aplicación:
// Uso del singleton
try {
ResultSet rs = DatabaseConnection.INSTANCE.executeQuery("SELECT * FROM users");
while (rs.next()) {
System.out.println(rs.getString("username"));
}
} catch (SQLException e) {
e.printStackTrace();
}
// Al finalizar la aplicación
DatabaseConnection.INSTANCE.closeConnection();
Las ventajas de usar un enum para el patrón Singleton incluyen:
- Es thread-safe por defecto
- Serialización segura sin implementación adicional
- Inmunidad a ataques de reflexión
- Instanciación perezosa garantizada por la JVM
Strategy Pattern
El patrón Strategy permite seleccionar un algoritmo en tiempo de ejecución:
public enum CompressionStrategy {
ZIP {
@Override
public void compress(String source, String target) {
System.out.println("Comprimiendo " + source + " a " + target + " usando ZIP");
// Implementación real aquí
}
@Override
public void decompress(String source, String target) {
System.out.println("Descomprimiendo " + source + " a " + target + " usando ZIP");
// Implementación real aquí
}
},
GZIP {
@Override
public void compress(String source, String target) {
System.out.println("Comprimiendo " + source + " a " + target + " usando GZIP");
// Implementación real aquí
}
@Override
public void decompress(String source, String target) {
System.out.println("Descomprimiendo " + source + " a " + target + " usando GZIP");
// Implementación real aquí
}
},
BZIP2 {
@Override
public void compress(String source, String target) {
System.out.println("Comprimiendo " + source + " a " + target + " usando BZIP2");
// Implementación real aquí
}
@Override
public void decompress(String source, String target) {
System.out.println("Descomprimiendo " + source + " a " + target + " usando BZIP2");
// Implementación real aquí
}
};
public abstract void compress(String source, String target);
public abstract void decompress(String source, String target);
// Método de fábrica para seleccionar una estrategia basada en la extensión
public static CompressionStrategy fromFileExtension(String fileName) {
if (fileName.endsWith(".zip")) {
return ZIP;
} else if (fileName.endsWith(".gz")) {
return GZIP;
} else if (fileName.endsWith(".bz2")) {
return BZIP2;
} else {
// Estrategia por defecto
return ZIP;
}
}
}
Uso del patrón Strategy:
// Seleccionar estrategia explícitamente
CompressionStrategy strategy = CompressionStrategy.GZIP;
strategy.compress("file.txt", "file.txt.gz");
// O seleccionar basado en el nombre de archivo
String fileName = "document.txt.bz2";
CompressionStrategy autoStrategy = CompressionStrategy.fromFileExtension(fileName);
autoStrategy.decompress(fileName, "document.txt");
State Pattern
El patrón State permite que un objeto altere su comportamiento cuando su estado interno cambia:
public enum EstadoPedido {
NUEVO {
@Override
public EstadoPedido siguienteEstado() {
return CONFIRMADO;
}
@Override
public boolean puedeModificar() {
return true;
}
@Override
public String getDescripcion() {
return "Pedido registrado, pendiente de confirmación";
}
},
CONFIRMADO {
@Override
public EstadoPedido siguienteEstado() {
return EN_PREPARACION;
}
@Override
public boolean puedeModificar() {
return true;
}
@Override
public String getDescripcion() {
return "Pedido confirmado, pendiente de preparación";
}
},
EN_PREPARACION {
@Override
public EstadoPedido siguienteEstado() {
return ENVIADO;
}
@Override
public boolean puedeModificar() {
return false;
}
@Override
public String getDescripcion() {
return "Pedido en proceso de preparación";
}
},
ENVIADO {
@Override
public EstadoPedido siguienteEstado() {
return ENTREGADO;
}
@Override
public boolean puedeModificar() {
return false;
}
@Override
public String getDescripcion() {
return "Pedido enviado, en ruta de entrega";
}
},
ENTREGADO {
@Override
public EstadoPedido siguienteEstado() {
// Estado final, no hay siguiente
return this;
}
@Override
public boolean puedeModificar() {
return false;
}
@Override
public String getDescripcion() {
return "Pedido entregado al cliente";
}
};
// Métodos abstractos que cada estado debe implementar
public abstract EstadoPedido siguienteEstado();
public abstract boolean puedeModificar();
public abstract String getDescripcion();
}
Ahora podemos usar este enum en una clase Pedido
:
public class Pedido {
private EstadoPedido estado = EstadoPedido.NUEVO;
private final List<String> items = new ArrayList<>();
private final String clienteId;
public Pedido(String clienteId) {
this.clienteId = clienteId;
}
public void agregarItem(String item) {
if (estado.puedeModificar()) {
items.add(item);
} else {
throw new IllegalStateException(
"No se puede modificar el pedido en estado " + estado);
}
}
public void avanzarEstado() {
estado = estado.siguienteEstado();
System.out.println("Pedido " + clienteId + ": " + estado.getDescripcion());
}
public EstadoPedido getEstado() {
return estado;
}
public List<String> getItems() {
return Collections.unmodifiableList(items);
}
}
Y así se utilizaría:
Pedido pedido = new Pedido("CUST-001");
pedido.agregarItem("Laptop");
pedido.agregarItem("Mouse");
pedido.avanzarEstado(); // A CONFIRMADO
pedido.agregarItem("Teclado"); // Aún se puede modificar
pedido.avanzarEstado(); // A EN_PREPARACION
// pedido.agregarItem("Monitor"); // Esto lanzaría una excepción
Command Pattern
El patrón Command encapsula una solicitud como un objeto:
public enum EditorCommand {
COPY {
@Override
public void execute(Editor editor) {
editor.copy();
}
@Override
public String getDescription() {
return "Copiar texto seleccionado";
}
},
CUT {
@Override
public void execute(Editor editor) {
editor.cut();
}
@Override
public String getDescription() {
return "Cortar texto seleccionado";
}
},
PASTE {
@Override
public void execute(Editor editor) {
editor.paste();
}
@Override
public String getDescription() {
return "Pegar texto del portapapeles";
}
},
UNDO {
@Override
public void execute(Editor editor) {
editor.undo();
}
@Override
public String getDescription() {
return "Deshacer última acción";
}
};
public abstract void execute(Editor editor);
public abstract String getDescription();
// Método para mapear teclas a comandos
public static EditorCommand fromKeyBinding(String keyBinding) {
return switch (keyBinding) {
case "ctrl+c" -> COPY;
case "ctrl+x" -> CUT;
case "ctrl+v" -> PASTE;
case "ctrl+z" -> UNDO;
default -> throw new IllegalArgumentException("Atajo de teclado no reconocido: " + keyBinding);
};
}
}
Uso del patrón Command:
Editor editor = new Editor();
// Ejecutar comandos directamente
EditorCommand.PASTE.execute(editor);
// O a través de atajos de teclado
String userKeyBinding = "ctrl+c";
try {
EditorCommand command = EditorCommand.fromKeyBinding(userKeyBinding);
command.execute(editor);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
Alternativa a estructuras if-else y switch complejas
Los enums pueden reemplazar bloques complejos de if-else
o switch
:
// Enfoque tradicional con if-else
public double calcularDescuento(String dia, double precioBase) {
if ("LUNES".equals(dia)) {
return precioBase * 0.1; // 10% descuento
} else if ("MARTES".equals(dia)) {
return precioBase * 0.2; // 20% descuento
} else if ("MIERCOLES".equals(dia)) {
return precioBase * 0.3; // 30% descuento
} // ... y más condiciones
}
Usando enums:
public enum DiaSemana {
LUNES(0.1),
MARTES(0.2),
MIERCOLES(0.3),
JUEVES(0.4),
VIERNES(0.5),
SABADO(0),
DOMINGO(0);
private final double factorDescuento;
DiaSemana(double factorDescuento) {
this.factorDescuento = factorDescuento;
}
public double calcularDescuento(double precioBase) {
return precioBase * factorDescuento;
}
// Método para convertir String a DiaSemana de forma segura
public static DiaSemana fromString(String dia) {
try {
return valueOf(dia.toUpperCase());
} catch (IllegalArgumentException e) {
return DOMINGO; // Valor por defecto
}
}
}
Este enfoque tiene varias ventajas:
- Seguridad de tipos: no se pueden pasar valores inválidos
- Encapsulación de la lógica específica a cada constante
- Mayor legibilidad y mantenibilidad
- Facilidad para extender el comportamiento
- Menor propensión a errores
Ejercicios de esta lección Enumeraciones Enums
Evalúa tus conocimientos de esta lección Enumeraciones Enums con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Clases abstractas
Listas
Métodos de la clase String
Streams: reduce()
Polimorfismo
Pattern Matching
Streams: flatMap()
Llamada y sobrecarga de funciones
Métodos referenciados
Métodos de la clase String
Representación de Fecha
Operadores lógicos
Inferencia de tipos con var
Tipos de datos
Estructuras de iteración
Streams: forEach()
Objetos
Funciones lambda
Uso de Scanner
CRUD en Java de modelo Customer sobre un ArrayList
Tipos de variables
Streams: collect()
Operadores aritméticos
Arrays y matrices
Clases y objetos
Interfaz funcional Consumer
Interfaces
Enumeraciones Enums
API java.nio 2
API Optional
Interfaz funcional Function
Encapsulación
Interfaces
Uso de API Optional
Representación de Hora
Herencia básica
Clases y objetos
Interfaz funcional Supplier
HashMap
Sobrecarga de métodos
Polimorfismo de tiempo de ejecución
OOP en Java
Sobrecarga de métodos
Clases sealed
Creación de Streams
Records
Encapsulación
Streams: min max
Métodos avanzados de la clase String
Funciones
Polimorfismo de tiempo de compilación
Reto sintaxis Java
Conjuntos
Estructuras de control
Recursión
Excepciones
Herencia avanzada
Estructuras de selección
Uso de interfaces
Operadores
Variables
HashSet
Objeto Scanner
Streams: filter()
Operaciones de Streams
Interfaz funcional Predicate
Streams: sorted()
Configuración de entorno
CRUD en Java de modelo Customer sobre un HashMap
Uso de variables
Clases
Streams: distinct()
Streams: count()
ArrayList
Datos de referencia
Interfaces funcionales
Métodos básicos de la clase String
Tipos de datos
Clases abstractas
Instalación
Funciones
Excepciones
Estructuras de control
Herencia de clases
La clase Scanner
Generics
Streams: map()
Funciones y encapsulamiento
Streams: match
Gestión de errores y excepciones
Datos primitivos
Todas las lecciones de Java
Accede a todas las lecciones de Java y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Instalación De Java
Introducción Y Entorno
Configuración De Entorno Java
Introducción Y Entorno
Tipos De Datos
Sintaxis
Variables
Sintaxis
Operadores
Sintaxis
Estructuras De Control
Sintaxis
Funciones
Sintaxis
Recursión
Sintaxis
Excepciones
Programación Orientada A Objetos
Clases Y Objetos
Programación Orientada A Objetos
Encapsulación
Programación Orientada A Objetos
Herencia
Programación Orientada A Objetos
Clases Abstractas
Programación Orientada A Objetos
Interfaces
Programación Orientada A Objetos
Sobrecarga De Métodos
Programación Orientada A Objetos
Polimorfismo
Programación Orientada A Objetos
La Clase Scanner
Programación Orientada A Objetos
Métodos De La Clase String
Programación Orientada A Objetos
Records
Programación Orientada A Objetos
Pattern Matching
Programación Orientada A Objetos
Inferencia De Tipos Con Var
Programación Orientada A Objetos
Enumeraciones Enums
Programación Orientada A Objetos
Generics
Programación Orientada A Objetos
Clases Sealed
Programación Orientada A Objetos
Listas
Framework Collections
Conjuntos
Framework Collections
Mapas
Framework Collections
Funciones Lambda
Programación Funcional
Interfaz Funcional Consumer
Programación Funcional
Interfaz Funcional Predicate
Programación Funcional
Interfaz Funcional Supplier
Programación Funcional
Interfaz Funcional Function
Programación Funcional
Métodos Referenciados
Programación Funcional
Creación De Streams
Programación Funcional
Operaciones Intermedias Con Streams: Map()
Programación Funcional
Operaciones Intermedias Con Streams: Filter()
Programación Funcional
Operaciones Intermedias Con Streams: Distinct()
Programación Funcional
Operaciones Finales Con Streams: Collect()
Programación Funcional
Operaciones Finales Con Streams: Min Max
Programación Funcional
Operaciones Intermedias Con Streams: Flatmap()
Programación Funcional
Operaciones Intermedias Con Streams: Sorted()
Programación Funcional
Operaciones Finales Con Streams: Reduce()
Programación Funcional
Operaciones Finales Con Streams: Foreach()
Programación Funcional
Operaciones Finales Con Streams: Count()
Programación Funcional
Operaciones Finales Con Streams: Match
Programación Funcional
Api Optional
Programación Funcional
Api Java.nio 2
Entrada Y Salida (Io)
Api Java.time
Api Java.time
Ecosistema Jakarta Ee De Java
Frameworks Para Java
Certificados de superación de Java
Supera todos los ejercicios de programación del curso de Java y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender el concepto y sintaxis básica de las enumeraciones en Java
- Aprender a declarar y utilizar enumeraciones con constantes
- Explorar métodos y constructores en enums
- Implementar patrones de diseño como Singleton y Strategy con enums
- Descubrir cómo las enumeraciones pueden albergar comportamientos personalizados
- Aplicar enums en la gestión de estados y comandos de una aplicación