Durante la programmazione, spesso incontriamo la necessità di limitare l'insieme di valori validi per un determinato tipo di dati. Quindi, ad esempio, il giorno della settimana può avere 7 valori diversi, il mese dell'anno può averne 12 e la stagione può averne 4. Per risolvere tali problemi, molti linguaggi di programmazione tipizzati staticamente forniscono un tipo di dati speciale: enumerazione ( I membri enum sono istanze
Gli elementi
enum
). L'enumerazione non è apparsa immediatamente in Java. Un costrutto linguistico specializzato enum
è stato introdotto a partire dalla versione 1.5. Fino a questo punto, i programmatori hanno utilizzato altri metodi per implementare le enumerazioni.
costrutto enum
Cominciamo con un esempio.enum
Descriviamo il tipo di dati per memorizzare il periodo dell'anno utilizzando :
enum Season { WINTER, SPRING, SUMMER, AUTUMN }
Bene, un semplice esempio del suo utilizzo:
Season season = Season.SPRING;
if (season == Season.SPRING) season = Season.SUMMER;
System.out.println(season);
Di conseguenza, SUMMER verrà stampato sulla console . Penso che l'esempio sia ovvio e non abbia bisogno di spiegazioni.
Enum è una classe
Dichiarandoenum
, creiamo implicitamente una classe derivata da java.lang.Enum
. Convenzionalmente la costruzione enum Season { ... }
è equivalente a class Season extends java.lang.Enum { ... }
. E sebbene il compilatore non ci consenta di ereditare esplicitamente da java.lang.Enum
noi, è comunque facile verificare che enum
venga ereditato utilizzando reflection
:
System.out.println(Season.class.getSuperclass());
Sulla console verrà visualizzato quanto segue:
class java.lang.Enum
L'ereditarietà effettiva viene eseguita automaticamente per noi dal compilatore Java. Successivamente, accettiamo di chiamare la classe creata dal compilatore per implementare l'enumerazione -class enum
e i possibili valori del tipo enumerato come enum
elementi -a.
I membri enum sono istanze enum
di una classe accessibili staticamente
Gli elementi enum Season (WINTER, SPRING и т.д.)
sono istanze accessibili staticamente enum
della -class Season
. La loro disponibilità statica ci consente di eseguire confronti utilizzando l'operatore di confronto di riferimento ==
. Esempio:
Season season = Season.SUMMER;
if (season == Season.AUTUMN) season = Season.WINTER;
Nome e numero di serie dell'elemento enum
Come accennato in precedenza, qualsiasienum
classe eredita java.lang.Enum
, che contiene una serie di metodi utili per tutte le enumerazioni. Esempio:
Season season = Season.WINTER;
System.out.println("season.name()=" + season.name() + " season.toString()=" + season.toString() + " season.ordinal()=" + season.ordinal());
L'output sarà:
season.name()=WINTER season.toString()=WINTER season.ordinal()=0
I metodi name()
, toString()
e sono mostrati qui ordinal()
. La semantica dei metodi è ovvia. Va notato che questi metodi enum
sono ereditati dalla classe java.lang.Enum
. Ottenere un elemento enum
tramite la rappresentazione in forma di stringa del suo nome Molto spesso si presenta il compito di ottenere un elemento enum
tramite la sua rappresentazione in forma di stringa. A questi scopi, in ogni enum
classe, il compilatore crea automaticamente uno speciale metodo statico: public static EnumClass valueOf(String name)
, che restituisce un elemento di enumerazione EnumClass
con nome uguale a name
. Esempio di utilizzo:
String name = "WINTER";
Season season = Season.valueOf(name);
Come risultato dell'esecuzione del codice, la variabile stagione sarà uguale a Season.WINTER
. Tieni presente che se l'elemento non viene trovato, verrà lanciata una IllegalArgumentException e, se è name
uguale null
, verrà lanciata una NullPointerException . A proposito, questo viene spesso dimenticato. Per qualche ragione, molti sono fermamente convinti che se una funzione accetta un argomento e in determinate condizioni lancia una IllegalArgumentException , quando la passa lì , null
verrà sicuramente lanciata anche una IllegalArgumentException . Ma non è questo il punto. Continuiamo. Ottenere tutti gli elementi di un'enumerazione A volte è necessario ottenere un elenco di tutti gli elementi enum
di una classe in fase di esecuzione. Per questi scopi, enum
il compilatore crea un metodo in ogni -class public static EnumClass[] values()
. Esempio di utilizzo:
System.out.println(Arrays.toString(Season.values()));
Otteniamo il seguente output:
[WINTER, SPRING, SUMMER, AUTUMN]
Si noti che né il metodo valueOf()
né il metodo values()
sono definiti nella classe java.lang.Enum
. Invece, vengono aggiunti automaticamente dal compilatore quando enum
viene compilata la classe. Aggiungere i propri metodi alla enum
-class Hai l'opportunità di aggiungere i tuoi metodi sia alla enum
-class che ai suoi elementi: Lo stesso, ma con polimorfismo: L'ultimo esempio dimostra l'uso dell'ereditarietà in enum
. Ne parleremo più avanti. L'ereditarietàenum
in Java enum
consente di implementare una gerarchia di classi, i cui oggetti vengono creati in una singola istanza e sono accessibili staticamente. In questo caso, gli elementi enum
possono contenere i propri costruttori. Facciamo un esempio: qui dichiariamo un'enumerazione Type
con tre elementi INT
, INTEGER
e STRING
. Il compilatore creerà le seguenti classi e oggetti:
Type
- classe derivata dajava.lang.Enum
INT
— oggetto della 1a classe derivata daType
INTEGER
— oggetto della 2a classe derivata daType
STRING
— oggetto della 3a classe derivata daType
Object parse(String)
e un costruttore polimorfico Type(..., boolean)
. Allo stesso tempo, gli oggetti delle classi INT
, INTEGER
e STRING
esistono in un'unica copia e sono accessibili staticamente. Puoi verificarlo:
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());
Otteniamo il seguente output:
class Type
class Type$1 class Type
class Type$2 class Type
class Type$3 class Type
Si può vedere che il compilatore ha creato una classe Type
e 3 nested
classi derivate da Type
.
Classe enum decompilata con ereditarietà
Per confermare quanto sopra, presentiamo anche il risultato della decompilazione dell'enumerazioneType
dall'esempio sopra:
Enumerazioni e polimorfismo parametrico
Il lettore potrebbe chiedersi: " Perché l'enumerazione Type di cui sopra non utilizza i generici? " Il fatto è che in Java èenum
vietato l'uso di farmaci generici. Quindi il seguente esempio non verrà compilato:
enum Type<T> {}
Ulteriori studi
Per una comprensione più approfondita di come funzionano le enumerazioni in Java, ti consiglio di familiarizzare con il codice sorgente della classejava.lang.Enum
e di utilizzare anche il decompilatore Jad per studiare il codice generato. Inoltre, lo studio del codice sorgente della libreria Java è assolutamente necessario per comprendere quanti meccanismi Java funzionano ed è utile come riferimento per la progettazione orientata agli oggetti. Link alla fonte originale: http://alexander.lds.lg.ua/
GO TO FULL VERSION