Miglioramenti all'Istruzione Switch in Java

Concetti Chiave
  • L'istruzione switch è stata migliorata in JDK 14 con nuove funzionalità.
  • Le nuove funzionalità includono espressioni switch, l'istruzione yield, supporto per liste di costanti case e il case con freccia.
  • L'uso di una lista di costanti case semplifica il codice e riduce la complessità.
  • Le nuove funzionalità di switch offrono alternative più eleganti e gestibili rispetto agli approcci tradizionali.

Miglioramenti all'Istruzione Switch

L'istruzione switch è stata parte di Java fin dall'inizio. È un elemento cruciale delle istruzioni di controllo del programma di Java e fornisce un modo per implementare una scelta multipla.

Inoltre, switch è così fondamentale per la programmazione che si trova in una forma o nell'altra in altri linguaggi di programmazione popolari. La forma tradizionale di switch è stata descritta nelle lezioni precedenti. Questa è la forma di switch che è sempre stata parte di Java. A partire da JDK 14, switch è stata sostanzialmente migliorata con l'aggiunta di quattro nuove funzionalità, elencate di seguito:

  • Espressioni switch
  • L'istruzione yield
  • Supporto per una lista di costanti case
  • Il case con freccia.

Esamineremo in dettaglio tutte queste nuove caratteristiche in questa e nelle prossime lezioni. Di seguito, però, riportiamo una breve descrizione:

  • L'espressione switch è, essenzialmente, uno switch che produce un valore. Quindi, un'espressione switch può essere utilizzata sul lato destro di un'assegnazione, per esempio.
  • L'istruzione yield specifica un valore che viene prodotto da un'espressione switch.
  • Da JDK 14 è possibile avere più di una costante case in un'istruzione case attraverso l'uso di una lista di costanti.
  • Una seconda forma di case è stata aggiunta che utilizza una freccia (->) invece di due punti. La freccia conferisce a case nuove capacità.

Collettivamente, i miglioramenti a switch rappresentano un cambiamento abbastanza significativo nel linguaggio Java. Non solo forniscono nuove capacità, ma in alcune situazioni, offrono anche alternative superiori agli approcci tradizionali. Per questo motivo, una solida comprensione del "come" e del "perché" dietro le nuove funzionalità di switch è importante.

Uno dei modi migliori per comprendere i miglioramenti di switch è iniziare con un esempio che utilizza uno switch tradizionale e poi incorporare gradualmente ogni nuova funzionalità. In questo modo, l'uso e il beneficio dei miglioramenti sarà chiaramente evidente.

Per iniziare, immaginiamo qualche dispositivo che produce codici interi che indicano vari eventi e vogliamo associare un livello di priorità ad ogni codice evento. La maggior parte degli eventi avrà una priorità normale, ma alcuni avranno una priorità più alta. Ecco un programma che utilizza un'istruzione switch tradizionale per fornire un livello di priorità dato un codice evento:

// Usa uno switch tradizionale
// per impostare un livello di priorità
// basato su una corrispondenza di codice evento.
class SwitchTradizionale {

    public static void main(String[] args) {

        // Inizializza il livello di priorità
        // e il codice evento.
        int livelloPriorita;
        int codiceEvento = 6010;

        // Uno switch tradizionale che fornisce un valore associato
        // con un case.
        switch (codiceEvento) {
            // In questo switch tradizionale
            // viene utilizzato l'impilamento dei case.
            case 1000:
            case 1205:
            case 8900:
                livelloPriorita = 1;
                break;

            case 2000:
            case 6010:
            case 9128:
                livelloPriorita = 2;
                break;

            case 1002:
            case 7023:
            case 9300:
                livelloPriorita = 3;
                break;

            // Priorità normale
            default:
                livelloPriorita = 0;
        }

        // Stampa il livello di priorità
        System.out.println("Livello di priorità per il codice evento " +
                           codiceEvento +
                           " è " + livelloPriorita);
    }

}

L'output è mostrato qui:

Livello di priorità per il codice evento 6010 è 2

Non c'è certamente nulla di sbagliato nell'utilizzare uno switch tradizionale come mostrato nel programma, e questo è il modo in cui il codice Java è stato scritto per più di due decenni. Tuttavia, come mostreranno le lezioni seguenti, in molti casi, lo switch tradizionale può essere migliorato dall'uso delle nuove funzionalità.

In questa lezione ci concentriamo sull'uso di una lista di costanti case.

Usare una Lista di Costanti case

Iniziamo con uno dei modi più semplici per modernizzare un switch tradizionale: utilizzando una lista di costanti case.

In passato, quando due costanti erano entrambe gestite dalla stessa sequenza di codice, veniva impiegato l'impilamento dei case, e questo è l'approccio utilizzato dal programma precedente. Ad esempio, ecco come vengono gestiti i case per 1000, 1205 e 8900:

case 1000:
case 1205:
case 8900:
    livelloPriorita = 1;
    break;

L'impilamento delle istruzioni case consente a tutti e tre i case di utilizzare la stessa sequenza di codice per impostare livelloPriorita a 1. Come spiegato nella lezione sulle istruzioni switch, in uno switch in stile tradizionale, l'impilamento dei case è reso possibile perché l'esecuzione passa attraverso ogni case finché non viene incontrato un break.

Sebbene questo approccio funzioni, una soluzione più elegante può essere raggiunta utilizzando una lista di costanti case.

A partire da JDK 14, è possibile specificare più di una costante case in un singolo case. Per fare ciò, è sufficiente separare ogni costante con una virgola.

Ad esempio, ecco un modo più compatto per codificare il case per 1000, 1205 e 8900 è mostrato di seguito:

// Usa una lista di costanti case
case 1000, 1205, 8900:
    livelloPriorita = 1;
    break;

A questo punto, il programma completo che utilizza una lista di costanti case è mostrato di seguito:

// Usa uno switch con liste di costanti
// per semplificare la gestione dei casi multipli.
class SwitchConListaCase {

    public static void main(String[] args) {

        // Inizializza il livello di priorità
        // e il codice evento.
        int livelloPriorita;
        int codiceEvento = 6010;

        // Uno switch con liste di costanti
        switch (codiceEvento) {
            case 1000, 1205, 8900:
                // Imposta il livello di priorità a 1
                // per i codici evento 1000, 1205 e 8900.
                livelloPriorita = 1;
                break;

            case 2000, 6010, 9128:
                // Imposta il livello di priorità a 2
                // per i codici evento 2000, 6010 e 9128.
                livelloPriorita = 2;
                break;

            case 1002, 7023, 9300:
                // Imposta il livello di priorità a 3
                // per i codici evento 1002, 7023 e 9300.
                livelloPriorita = 3;
                break;

            // Priorità normale
            default:
                livelloPriorita = 0;
        }

        // Stampa il livello di priorità
        System.out.println("Livello di priorità per il codice evento " +
                           codiceEvento +
                           " è " + livelloPriorita);
    }

}

Come possiamo vedere, il numero di istruzioni case è stato ridotto di sei, rendendo lo switch più facile da leggere e un po' più gestibile. Sebbene il supporto per una lista di costanti case non aggiunga di per sé alcuna funzionalità fondamentalmente nuova allo switch, aiuta a semplificare il codice. In molte situazioni, offre anche un modo facile per migliorare il codice esistente, specialmente quando in precedenza veniva impiegato un ampio impilamento di case. Pertanto, è una caratteristica che possiamo mettere in pratica immediatamente, con una minima riscrittura del codice.