Espressioni Switch e Istruzione Yield in Java

Concetti Chiave
  • Le espressioni switch in Java permettono di restituire un valore, semplificando la gestione delle scelte multiple.
  • L'istruzione yield consente di specificare il valore restituito da un'espressione switch.
  • Le nuove funzionalità di switch offrono un modo più elegante e conciso per gestire le scelte multiple rispetto agli approcci tradizionali.

Introduzione alle Espressioni switch e all'Istruzione yield

Tra i miglioramenti all'istruzione switch, quello che ha l'impatto più profondo è la switch expression. Una switch expression è, essenzialmente, uno switch che restituisce un valore. Quindi, ha tutte le capacità di un'istruzione switch tradizionale, più la capacità di produrre un risultato. Questa capacità aggiuntiva rende la switch expression una delle aggiunte più importanti a Java negli ultimi anni.

Un modo per fornire il valore di una switch expression è con la nuova istruzione yield. Ha questa forma generale:

yield valore;

Qui, valore è il valore risultante dell'espressione switch, e può essere qualsiasi espressione compatibile con il tipo di valore richiesto.

Un punto chiave da comprendere riguardo a yield è che termina immediatamente lo switch. Quindi, funziona in qualche modo come break, con la capacità aggiuntiva di fornire un valore. È importante sottolineare che yield è una parola chiave sensibile al contesto. Questo significa che al di fuori del suo uso in una switch expression, yield è semplicemente un identificatore senza significato speciale. Tuttavia, se si usa un metodo chiamato yield(), deve essere qualificato. Ad esempio, se yield() è un metodo non-static all'interno della sua classe, si deve usare this.yield().

È molto facile specificare una switch expression. Basta usare lo switch in un contesto in cui è richiesto un valore, come sul lato destro di un'istruzione di assegnazione, un argomento a un metodo, o un valore di ritorno. Ad esempio, questa riga indica che viene impiegata una switch expression:

int x = switch(y) {
    // ...
}

Qui, il risultato dello switch viene assegnato alla variabile x. Un punto chiave sull'uso di una switch expression è che ogni case (più default) deve produrre un valore (a meno che non lanci un'eccezione). In altre parole, ogni percorso attraverso una switch expression deve produrre un risultato.

L'aggiunta della switch expression semplifica la codifica di situazioni in cui ogni case imposta il valore di qualche variabile. Tali situazioni possono verificarsi in diversi modi. Ad esempio, ogni case potrebbe impostare una variabile boolean che indica il successo o il fallimento di qualche azione intrapresa dal switch. Spesso, tuttavia, impostare una variabile è lo scopo principale del switch, come nel caso dello switch usato dal programma nella lezione precedente.

Il suo compito è produrre il livello di priorità associato a un codice evento. Con un'istruzione switch tradizionale, ogni istruzione case deve assegnare individualmente un valore alla variabile, e questa variabile diventa il risultato de facto del switch. Questo è l'approccio usato dai programmi precedenti, in cui il valore della variabile livelloPriorita viene impostato da ogni case. Sebbene questo approccio sia stato usato nei programmi Java per decenni, la switch expression offre una soluzione migliore perché il valore desiderato viene prodotto dal switch stesso.

La seguente versione del programma mette in azione la discussione precedente cambiando l'istruzione switch in una switch expression:

// Usa una switch expression per semplificare il codice.
class SwitchEspressione {

    public static void main(String[] args) {

        // Inizializza il codice evento
        int codiceEvento = 6010;

        // Usa una switch expression per determinare il livello di priorità
        int livelloPriorita = switch (codiceEvento) {
            case 1000, 1205, 8900:
                yield 1;

            case 2000, 6010, 9128:
                yield 2;

            case 1002, 7023, 9300:
                yield 3;

            // Priorità normale
            default:
                yield 0;
        };

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

}

Si osservi attentamente lo switch nel programma. Si noti che differisce in modi importanti da quello usato negli esempi delle lezioni precedenti. Invece di ogni case che assegna un valore a livelloPriorita individualmente, questa versione assegna il risultato dello switch stesso alla variabile livelloPriorita.

Quindi, è richiesta solo un'assegnazione a livelloPriorita, e la lunghezza dello switch è ridotta. Usare una switch expression assicura anche che ogni case produca un valore, evitando così la possibilità di dimenticare di dare un valore a livelloPriorita in uno dei case. Si noti che il valore dello switch viene prodotto dall'istruzione yield all'interno di ogni case. Come spiegato, yield causa la terminazione immediata dello switch, quindi non si verificherà alcuna cascata da case a case. Quindi, nessuna istruzione break è richiesta, o consentita. Un'altra cosa da notare è il punto e virgola dopo la parentesi graffa di chiusura dello switch. Poiché questo switch viene usato in un'assegnazione, deve essere terminato da un punto e virgola.

C'è una restrizione importante che si applica a una switch expression: le istruzioni case devono gestire tutti i valori che potrebbero verificarsi. Quindi, una switch expression deve essere esaustiva. Ad esempio, se la sua espressione di controllo è di tipo int, allora tutti i valori int devono essere gestiti dal switch. Questo costituirebbe, ovviamente, un numero molto grande di istruzioni case! Per questa ragione, la maggior parte delle switch expression deve avere un'istruzione default. L'eccezione a questa regola è quando viene usata un'enumerazione, e ogni valore dell'enumerazione è abbinato da un case.