Al programar, a menudo nos encontramos con la necesidad de limitar el conjunto de valores válidos para un determinado tipo de datos. Entonces, por ejemplo, el día de la semana puede tener 7 valores diferentes, el mes del año puede tener 12 y la estación puede tener 4. Para resolver tales problemas, muchos lenguajes de programación de tipo estático proporcionan un tipo de datos especial: enumeración ( Los miembros de Enum son instancias
Los elementos
enum
). La enumeración no apareció en Java de inmediato. enum
Se introdujo una construcción de lenguaje especializado a partir de la versión 1.5. Hasta este punto, los programadores han utilizado otros métodos para implementar enumeraciones.
construcción de enumeración
Comencemos con un ejemplo. Describamosenum
el tipo de datos para almacenar la temporada usando:
enum Season { WINTER, SPRING, SUMMER, AUTUMN }
Bueno, un ejemplo sencillo de su uso:
Season season = Season.SPRING;
if (season == Season.SPRING) season = Season.SUMMER;
System.out.println(season);
Como resultado de lo cual SUMMER se imprimirá en la consola . Creo que el ejemplo es obvio y no necesita explicación.
Enum es una clase
Al declararenum
, creamos implícitamente una clase derivada de java.lang.Enum
. Convencionalmente, la construcción enum Season { ... }
equivale a class Season extends java.lang.Enum { ... }
. Y aunque el compilador no nos permite heredar explícitamente de java.lang.Enum
nosotros, aún así es fácil verificar que enum
se hereda usando reflection
:
System.out.println(Season.class.getSuperclass());
En la consola se mostrará lo siguiente:
class java.lang.Enum
La herencia real la realiza automáticamente el compilador de Java. A continuación, acordemos llamar a la clase creada por el compilador para implementar la enumeración la enum
clase -y los posibles valores del tipo enumerado como enum
elementos -a.
Los miembros de Enum son instancias enum
de una clase a la que se puede acceder estáticamente.
Los elementos enum Season (WINTER, SPRING и т.д.)
son instancias estáticamente accesibles enum
de la clase -class Season
. Su disponibilidad estática nos permite realizar comparaciones utilizando el operador de comparación de referencia ==
. Ejemplo:
Season season = Season.SUMMER;
if (season == Season.AUTUMN) season = Season.WINTER;
Nombre y número de serie del elemento enum
Como se mencionó anteriormente, cualquierenum
clase hereda java.lang.Enum
, que contiene una serie de métodos útiles para todas las enumeraciones. Ejemplo:
Season season = Season.WINTER;
System.out.println("season.name()=" + season.name() + " season.toString()=" + season.toString() + " season.ordinal()=" + season.ordinal());
La salida será:
season.name()=WINTER season.toString()=WINTER season.ordinal()=0
Los métodos name()
y toString()
se muestran aquí ordinal()
. La semántica de los métodos es obvia. Cabe señalar que estos métodos enum
se heredan de la clase java.lang.Enum
. Obtener un elemento enum
mediante la representación en cadena de su nombre Muy a menudo surge la tarea de obtener un elemento enum
mediante su representación en cadena. Para estos fines, en cada enum
clase, el compilador crea automáticamente un método estático especial: public static EnumClass valueOf(String name)
, que devuelve un elemento de enumeración EnumClass
con un nombre igual a name
. Ejemplo de uso:
String name = "WINTER";
Season season = Season.valueOf(name);
Como resultado de ejecutar el código, la variable temporada será igual a Season.WINTER
. Tenga en cuenta que si no se encuentra el elemento, se generará una IllegalArgumentException y, si es name
igual null
, se generará una NullPointerException . Por cierto, esto a menudo se olvida. Por alguna razón, muchos están firmemente convencidos de que si una función toma un argumento y, bajo ciertas condiciones, arroja una IllegalArgumentException , al pasarla allí , null
seguramente también se lanzará una IllegalArgumentException . Pero eso no viene al caso. Continuemos. Obtener todos los elementos de una enumeración A veces es necesario obtener una lista de todos los elementos enum
de una clase en tiempo de ejecución. Para estos fines, enum
el compilador crea un método en cada clase public static EnumClass[] values()
. Ejemplo de uso:
System.out.println(Arrays.toString(Season.values()));
Obtenemos el siguiente resultado:
[WINTER, SPRING, SUMMER, AUTUMN]
Tenga en cuenta que ni método valueOf()
ni método values()
están definidos en la clase java.lang.Enum
. En cambio, el compilador los agrega automáticamente cuando enum
se compila la clase. Agregar tus propios métodos a enum
la clase Tienes la oportunidad de agregar tus propios métodos tanto a la enum
clase como a sus elementos: Lo mismo, pero con polimorfismo: El último ejemplo demuestra el uso de la herencia en enum
. Más sobre esto más adelante. La herenciaenum
en Java enum
le permite implementar una jerarquía de clases, cuyos objetos se crean en una sola instancia y son accesibles estáticamente. En este caso, los elementos enum
pueden contener sus propios constructores. Pongamos un ejemplo: aquí declaramos una enumeración con Type
tres elementos INT
y INTEGER
. STRING
El compilador creará las siguientes clases y objetos:
Type
- clase derivada dejava.lang.Enum
INT
— objeto de primera clase derivado deType
INTEGER
— objeto de segunda clase derivado deType
STRING
— objeto de tercera clase derivado deType
Object parse(String)
y un constructor polimórficos Type(..., boolean)
. Al mismo tiempo, los objetos de las clases INT
existen en una sola copia y son accesibles estáticamente INTEGER
. STRING
Puedes verificar esto:
System.out.println(Type.class);
System.out.println(Type.INT.getClass() + " " + Type.INT.getClass().getSuperclass());
System.out.println(Type.INTEGER.getClass() + " " + Type.INTEGER.getClass().getSuperclass());
System.out.println(Type.STRING.getClass() + " " + Type.STRING.getClass().getSuperclass());
Obtenemos el siguiente resultado:
class Type
class Type$1 class Type
class Type$2 class Type
class Type$3 class Type
Se puede ver que el compilador creó una clase Type
y 3 nested
clases derivadas de Type
.
Clase de enumeración descompilada con herencia
Para confirmar lo anterior, también presentamos el resultado de descompilar la enumeraciónType
del ejemplo anterior:
Enumeraciones y polimorfismo paramétrico.
El lector puede preguntarse: "¿ Por qué la enumeración de tipos anterior no utiliza genéricos? " El caso es que en Java estáenum
prohibido el uso de genéricos. Entonces el siguiente ejemplo no se compilará:
enum Type<T> {}
Estudio adicional
Para una comprensión más profunda de cómo funcionan las enumeraciones en Java, le recomiendo que se familiarice con el código fuente de la clasejava.lang.Enum
y también utilice el descompilador Jad para estudiar el código generado. Además, estudiar el código fuente de la biblioteca Java es absolutamente necesario para comprender cuántos mecanismos de Java funcionan y es útil como referencia para el diseño orientado a objetos. Enlace a la fuente original: http://alexander.lds.lg.ua/
GO TO FULL VERSION