Introducción a enum en Java

Los enumerados son tipos de datos especiales que pueden adoptar un número finito de valores, como contraparte a un tipo de datos más abierto como número, que suele aceptar miles de millones de valores, o cadena de caracteres, que puede adoptar cualquier cadena representable. En Java, la palabra clave enum se usa para fabricar tipos enumerados, con los que puedes aplicar restricciones de tipos que se validan en el momento de compilar.

Un tipo enumerado es un tipo de datos personalizado que admite como posibles valores para las variables de ese tipo, solamente aquellos que formen parte de una lista finita de posibles valores. Estos posibles valores los especificas cuando defines el tipo enumerado en código.

Por ejemplo, podrías definir el tipo de datos enumerado DíaDeLaSemana, de tal manera que una hipotética variable de este tipo sólo pueda tener como valor LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO y DOMINGO.

La diferencia entre usar un tipo enumerado y adoptar, por ejemplo, una variable de tipo string o de tipo int, es que hay miles de millones de int posibles que le puedes asignar a una variable, y hay infinitas cadenas de caracteres que podrías fabricar, por lo que tendrías que validar en código que el valor que guarda esa variable sea correcto (por ejemplo, que sea un número comprendido entre 1 y 7 o que la cadena de caracteres sea únicamente una de la lista de posibles cadenas).

En cambio, con un tipo enumerado, vas a poder especificar los posibles identificadores que puede tener la variable, y asignarle cualquier otra cosa que no sea uno de los identificadores válidos será un error.


En Java, para fabricar un tipo enumerado, utilizas la palabra clave enum. Un enum se declara de forma parecida a una clase o a un registro, pero usando la palabra clave enum. Por ejemplo,

public enum DiaDeLaSemana {

}

Y tiene sentido que se haga así, porque en realidad un enumerado es una clase especial. Extiende de Enum, y aunque no se interactúa normalmente directamente con ella como si fuese una clase, tiene métodos y atributos.

La diferencia fundamental entre clase y enum en Java es que, si bien una clase la puedes instanciar en función de lo que diga su constructor, no puedes instanciar un tipo enumerado. Cuando declaras en código la existencia de ese enumerado, estableces los identificadores de las instancias que quieres que existan, y sólo ellas van a existir.

Para declarar estas instancias, especificas los identificadores separados por comas. Por ejemplo:

public enum PuntoCardinal {
  NORTE,
  SUR,
  ESTE,
  OESTE
}

De este modo, se crean cuatro identificadores que son equivalentes a un campo static final. Esta es la razón por la que lo normal es que los identificadores de un enumerado se escriban en mayúsculas: porque son constantes.

A partir de este momento, se podrá declarar una variable de tiop PuntoCardinal y utilizar estos identificadores en código.

Por ejemplo, podrías declarar una variable de este modo en una aplicación de GPS:

public class Gps {
  private PuntoCardinal direccion = PuntoCardinal.NORTE;

  public Gps() {
    PuntoCardinal otro = PuntoCardinal.SUR;
  }
}

Como puedes ver, para usar el identificador tendrás que acceder a él poniendo la clase como prefijo, igual que si usases cualquier otro campo. La alternativa sería usar import static para no tener que poner el nombre de la clase, importando el identificador de forma estática.

Finalmente, dado que los identificadores de un enumerado son valores, son perfectamente compatibles con las comparaciones mediante el operador ==, ya que como sólo existen esas instancias, la comparación es válida.

public void apuntaSureste(PuntoCardinal p) {
  return p == PuntoCardinal.SUR || p == PuntoCardinal.ESTE;
}

public void direccion(Punto p) {
  switch (p) {
    case NORTE:
      System.out.println("Norte");
      break;
    case SUR:
      System.out.println("Sur");
      break;
    case ESTE:
      System.out.println("Este");
      break;
    case OESTE:
      System.out.println("Oeste");
      break;
}

Aprecia que en el caso del switch, no necesitas poner el nombre de la clase en los case. Como switch nota que el tipo de datos p es enumerado, se da por hecho que los identificadores que van a ir en los case van a ser de ese tipo, haciendo innecesario aclararlo otra vez.

Los identificadores de un enumerado no pueden ser usados en operaciones aritméticas, por lo que solamente tiene utilidad explicar cómo asignar o comparar identificadores.

Lista de reproducción
  1. 1
    ¿Cómo funciona Comparator en Java?
    10 minutos
  2. 2
    ¿Para qué sirve Override?
    4 minutos
  3. 3
    Cómo usar la clase Properties en Java
    14 minutos
  4. 4
    Interfaces funcionales y funciones flecha
    8 minutos
  5. 5
    Bloque static de Java: inicializadores estáticos y otros usos
    7 minutos
  6. 6
    import static, ¿para qué sirve?
    3 minutos
  7. 7
    Uso de Optional en Java
    10 minutos
  8. 8
    Introducción al Scanner de Java
    11 minutos
  9. 9
    ¿Para qué sirve el modificador static de Java?
    6 minutos
  10. 10
    Funciones variádicas en Java
    6 minutos
  11. 11
    Inner classes en Java
    8 minutos
  12. 12
    var en Java: una introducción para gente nueva
    7 minutos
  13. 13
    Switch expressions en Java
    10 minutos
  14. 14
    Java: del instanceof al Pattern Matching
    7 minutos
  15. 15
    Sealed classes en Java
    8 minutos
  16. 16
    Getters y setters o atributos públicos en Java, ¿qué es mejor?
    9 minutos
  17. 17
    El String[] args del método main de Java
    8 minutos
  18. 18
    Introducción a clases anónimas en Java
    6 minutos
  19. 19
    Introducción a enum en Java
    6 minutos