Istruzioni if e else in Java

Concetti Chiave
  • Le istruzioni if e else in Java sono utilizzate per controllare il flusso di esecuzione del programma in base a condizioni specifiche.
  • L'istruzione if esegue un blocco di codice se una condizione è vera, altrimenti può eseguire un blocco alternativo con else.
  • È possibile annidare istruzioni if per gestire condizioni multiple e utilizzare la struttura if-else-if per creare una scala di condizioni.

Istruzioni di controllo del flusso di esecuzione

Un linguaggio di programmazione utilizza istruzioni di controllo per far avanzare e diramare il flusso di esecuzione in base alle modifiche dello stato di un programma.

Le istruzioni di controllo di Java possono essere suddivise nelle seguenti categorie: selezione, iterazione e salto.

  • Le istruzioni di selezione consentono al programma di scegliere percorsi di esecuzione differenti in base al risultato di un'espressione o allo stato di una variabile.
  • Le istruzioni di iterazione permettono di ripetere una o più istruzioni (le istruzioni di iterazione formano i cicli).
  • Le istruzioni di salto consentono al programma di eseguire in modo non lineare.

Java supporta due istruzioni di selezione: if e switch. Queste istruzioni permettono di controllare il flusso di esecuzione del programma in base a condizioni note solo durante l'esecuzione.

Istruzione if e istruzione else

L'istruzione if è stata introdotta nelle lezioni precedenti. Qui andremo ad approfondirla.

L'istruzione if è l'istruzione di esecuzione condizionale di Java. Può essere utilizzata per instradare l'esecuzione del programma lungo due percorsi differenti. La forma generale dell'istruzione if è:

if (condizione) istruzione1;
else istruzione2;

Qui ciascuna istruzione può essere una singola istruzione o un'istruzione composta racchiusa tra parentesi graffe (un blocco). La condizione è qualsiasi espressione che restituisce un valore boolean. La clausola else è facoltativa.

L'if funziona così: se la condizione è vera, viene eseguita istruzione1. Altrimenti viene eseguita istruzione2 (se esiste). In nessun caso saranno eseguite entrambe le istruzioni. Per esempio:

int a, b;
// ...
if (a < b) a = 0;
else b = 0;

Qui, se a è minore di b, allora a viene impostata a zero. Altrimenti viene impostata a zero b. In nessun caso entrambe vengono poste a zero.

Solitamente l'espressione che controlla l'if coinvolge gli operatori relazionali. Non è però strettamente necessario. È possibile controllare l'if usando una singola variabile boolean, come in questo frammento di codice:

boolean datiDisponibili;
// ...
if (datiDisponibili)
    ElaboraDati();
else
    AttendiAltriDati();

Bisogna ricordare che può comparire una sola istruzione direttamente dopo if o else. Se occorrono più istruzioni è necessario creare un blocco, come in questo frammento:

int byteDisponibili;
// ...
if (byteDisponibili > 0) {
    ElaboraDati();
    byteDisponibili -= n;
} else
    AttendiAltriDati();

In questo caso entrambe le istruzioni all'interno del blocco if verranno eseguite se byteDisponibili è maggiore di zero.

Alcuni programmatori trovano comodo includere sempre le parentesi graffe con l'istruzione if, anche quando c'è una sola istruzione in ciascuna clausola. In questo modo è facile aggiungere in seguito un'altra istruzione e si evita di dimenticare le parentesi. Dimenticarle quando servono è infatti una causa comune di errori. Ad esempio:

int byteDisponibili;
// ...
if (byteDisponibili > 0) {
    ElaboraDati();
    byteDisponibili -= n;
} else
    AttendiAltriDati();
byteDisponibili = n;

È evidente che l'istruzione byteDisponibili = n; era destinata al blocco else, a giudicare dall'indentazione. Tuttavia, come già ricordato, gli spazi bianchi sono irrilevanti per Java e il compilatore non può sapere quale fosse l'intento. Il codice compila senza problemi ma si comporta in modo scorretto in esecuzione. L'esempio precedente è corretto nel codice seguente:

int byteDisponibili;
// ...
if (byteDisponibili > 0) {
    ElaboraDati();
    byteDisponibili -= n;
} else {
    AttendiAltriDati();
    byteDisponibili = n;
}

Istruzioni if annidate

Un nested if (ossia un if annidato) è un'istruzione if che rappresenta il target di un altro if o else. Gli if annidati sono molto comuni. Quando si annidano gli if occorre ricordare che una clausola else fa sempre riferimento all'if più vicino all'interno dello stesso blocco che non abbia già un else associato. Esempio:

if (i == 10) {
    if (j < 20) a = b;
    if (k > 100) c = d;    // questo if
    else a = c;            // associato a questo else
} else a = d;              // questo else si riferisce a if(i == 10)

Come indicano i commenti, l'else finale non è associato a if(j < 20) perché non appartiene allo stesso blocco (pur essendo l'if più vicino senza else). Piuttosto, l'else finale è associato a if(i == 10). L'else interno si riferisce a if(k > 100) perché è il più vicino all'interno dello stesso blocco.

La struttura if-else-if

Un costrutto di programmazione comune basato su una sequenza di if annidati è la scala if-else-if. Ha questa forma:

if(condizione)
    istruzione;
else if(condizione)
    istruzione;
else if(condizione)
    istruzione;
.
.
.
else
    istruzione;

Le istruzioni if sono valutate dall'alto verso il basso. Non appena una delle condizioni è true, viene eseguita l'istruzione associata e il resto della scala viene ignorato. Se nessuna condizione è vera, viene eseguita l'istruzione dello else finale. Quest'ultimo funge da condizione di default: se tutti gli altri test falliscono, viene eseguito l'ultimo else. Se non esiste else finale e tutte le condizioni sono false, non viene eseguita alcuna azione.

Segue un programma che utilizza una scala if-else-if per determinare in quale stagione si trova un determinato mese.

// Dimostrazione di istruzioni if-else-if.
class SeAltrimenti {
    public static void main(String[] args) {
        int mese = 4; // Aprile
        String stagione;

        if (mese == 12 || mese == 1 || mese == 2)
            stagione = "Inverno";
        else if (mese == 3 || mese == 4 || mese == 5)
            stagione = "Primavera";
        else if (mese == 6 || mese == 7 || mese == 8)
            stagione = "Estate";
        else if (mese == 9 || mese == 10 || mese == 11)
            stagione = "Autunno";
        else
            stagione = "Mese Non Valido";

        System.out.println("Aprile in " + stagione + ".");
    }
}

Ecco l'output prodotto dal programma:

Aprile è in Primavera.

Si consiglia di sperimentare con questo programma prima di proseguire. Come si noterà, qualunque valore venga assegnato a mese, all'interno della scala viene eseguita una e una sola istruzione di assegnazione.