Enum

Finora abbiamo visto come titi di dati, i tipi primitivi (int, double, boolean, char ......), i tipi da noi definito tramite la definizione di classi (tipi reference) con cui possiamo estendere i tipi di dati oltre quelli primitivi: definiamo ad esempio una classe Persona con due attributi nome di tipo String ed eta di tipo int. Questo è un nuovo tipo di dati oltre a quelli primitivi.

Ora vediamo un nuovo tipo di dato anche questo di tipo reference, il tipo enum, che permette di definire un tipo che può avere solo un certo numero di possibili valori (costanti), stabiliti nella definizione del tipo, ad esempio i giorni della settimana, i mesi dell'anno o altre costanti che molto spesso sono utili quando si programma. Vedi per trattazione argomento Enum: http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaEnum.html

NOTA

I tipi enum sono stati introdotti in Java SE versione 5.0 (anno 2004) quando la prima versione di Java (1.0) è del 1996. Nella api di alcune classi precedenti alla 5.0 si vede come venivano definite delle costanti non avendo la possibilità definirle come enum, e così sono rimaste per retro compatibilità con le vecchie versioni di Java: le constanti venivano definiti come attributi public static final int <NOME_COSTANTE> = <INT_VALUE>

Ad esempio per la classe java.util.Calendar https://docs.oracle.com/javase/7/docs/api/constant-values.html#java.util.Calendar classe per lavorare con le date definisce molte costanti. Vediamo un esempio di utilizzo e quali potrebbero essere i problemi che hanno portato all'inserimento dei tipi enum in java.

Vediamo l'esempio:

package esempio;

import java.util.Calendar;

public class TestCalendar {

	public static void main(String[] args) {
		Calendar rightNow = Calendar.getInstance();
		
		int mounthNumber = rightNow.get(Calendar.MONTH);
		
		System.out.println("Mounth number: " + mounthNumber);
		
		// the same as Calendar.MONTH
		mounthNumber = rightNow.get(2);
		
		System.out.println("Mounth number: " + mounthNumber);
		
		// compile time no problem ma eccezione java.lang.ArrayIndexOutOfBoundsException 
		// in esecuzione
		int value = rightNow.get(20);
		
		
	}

}

Si vede nell'esempio che il fatto di non avere l'enum e quindi di simulare le costanti con variabili static final non permette controlli in fase di compilazione come si avrebbero se si utilizzassero i tipi enum.

Eseguendo il programma ho il seguente errore in output:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 20
	at java.util.Calendar.internalGet(Calendar.java:1840)
	at java.util.Calendar.get(Calendar.java:1827)
	at esempio.TestCalendar.main(TestCalendar.java:18)

in quanto il valore 20 come parametro del metodo get() di Calendar non è tra quelli ammessi.

Le nuove classi per lavorare con le date e tempo sotto java.time invece utilizzano i tipi enumerativi (enum).

Esempio con le nuove classi di Java che utilizzano come parametri il tipo enum java.time.Month

package esempio;

import java.time.LocalDate;
import java.time.Month;

public class TestLocalDate {

	public static void main(String[] args) {
		LocalDate dateOfBirth = LocalDate.of(2012, Month.MAY, 14);
		LocalDate firstBirthday = dateOfBirth.plusYears(1);
		
		System.out.println("FirstBithday: " + firstBirthday);
	}

}

ESEMPI

Vedi esempi di enum: https://github.com/checksound/LezioneEnum

SUMMARY

Quando si possono usare enums? Ogni volta che abbiamo bisogno di un numero fisso di costanti, il cui valore è noto al tempo di compilazione (compile-time). Questi includono i tipi enumerativi naturali (come i giorni della settimana o i semi delle carte) o altri tipi di insiemi i cui valori sono conosciuti a priori (a compile-time) come la scelta di un menù di una GUI, i flag di un'interfaccia a riga di comando etc..

Proprietà del tipo enum:

  1. Enums sono type-safe (il controllo sulla validità del valore è eseguito in fase di compilazione);

  2. Enums creano il proprio namespace (esempio Stagione.ESTATE o Stagione.AUTUNNO se ho definito un enum Stagione { ESTATE, AUTUNNO, INVERNO, PRIMAVERA, ESTATE };

  3. Quando un enum è definito, una classe che estende java.lang.Enum è creata. Quindi un enum non può estendere un altro enum o una classe. Inoltre il compilatore crea una istanza della classe per ogni costante definita in enum. La classe java.lang.Enum ha questi metodi:

    public final String name();  // Returns the name of this enum constant, exactly as declared in its enum declaration.
                                 // You could also override the toString() to provide a more user-friendly description.
    public String toString();    // Returns the name of this enum constant, as contained in the declaration.
                                 // This method may be overridden.
    public final int ordinal();  // Returns the ordinal of this enumeration constant.
  4. Tutte le costanti definite in un enum sono public static final. Poiché sono static possono essere accedute tramite EnumName.instanceName.

  5. Non si istanzia un enum, ma utilizzano le costanti definite;

  6. Enums possono essere utilizzati negli statement di switch esattamente come i tipi int;

Last updated