# Java/Strutture di controllo

| Java Linguaggio Java categoria · sviluppo · Come posso contribuire? → Vai su Wikiversity | Java: Guida alla programmazioneJava/Introduzione - Specifica di linguaggio - Libreria standardJava/Comunicazione seriale Tipi di datoJava/Tipi di dato • EspressioniJava/Operatori • VariabiliJava/Variabili locali • IstruzioniJava/Istruzioni • Strutture di controlloJava/Strutture di controllo • PackageJava/Package Classi e oggettiJava/Classi e oggetti • OggettiJava/Oggetti • MetodiJava/Metodi • Metodi (cont.)Java/Metodi/2 • ArrayJava/Array Modificatori di accessoJava/Modificatori di accesso • EreditarietàJava/Ereditarietà Gestione delle eccezioniJava/Gestione delle eccezioni • GenericsJava/Generics Thread e parallelismoJava/Multithreading • Interblocco ricontrollatoJava/Interblocco ricontrollato Alcune differenze con il CJava/Concetti fondamentali • LessicoJava/Lessico • GrammaticaJava/Grammatica |

## Introduzione

In virtù del teorema di Böhm-Jacopini, ogni algoritmo può essere espresso in un linguaggio di programmazione che disponga di almeno tre strutture di controllo:
* almeno una struttura di sequenza;
* almeno una struttura selettiva;
* almeno una struttura iterativa.
Il Java dispone di queste strutture e anche di una struttura aggiuntiva per la gestione delle eccezioni.

## Sequenza delle istruzioni

Non esiste una sintassi specifica per la struttura di sequenza. La successione delle istruzioni è determinata dall'ordine in cui sono scritte nel codice sorgente del programma.
Sotto certe condizioni, il compilatore può cambiare l'ordine delle istruzioni localmente ad un metodo, e ciò ha conseguenze nei programmi multithreaded in cui i thread non sincronizzano correttamente gli accessi alle risorse condivise.
Invece, il programmatore non può sovvertire l'ordine in cui le istruzioni sono eseguite: l'istruzione goto, presente in altri linguaggi, è stata deliberatamente lasciata fuori dal Java.

## Strutture selettive
### if

Calcola una certa espressione booleana, ed esegue una scelta tra due istruzioni in base al valore ottenuto. Spesso una delle due istruzioni (o entrambe) sono in realtà dei blocchi di codice.
Oppure:
Si può realizzare una catena di if ... else if, come in C:

### switch

Calcola una certa espressione il cui compile-time type sia uno dei seguenti:
* char, byte, short, int
* Character, Byte, Short, Integer
* java.lang.Enum o sottotipo
* java.lang.String
ed esegue una scelta tra n vie, in base al valore calcolato.
La clausola default è facoltativa e indica le istruzioni che saranno eseguite se il valore calcolato non corrisponde a nessuno tra quelli indicati nelle etichette case. Non deve per forza stare in fondo al blocco, quindi può trovarsi anche all'inizio o in mezzo.
I valori che accompagnano le etichette case devono essere espressioni costanti e diverse tra loro.

#### L'espressione

Se l'espressione esaminata dallo switch è null, allora viene lanciata una NullPointerException.
Se il tipo dell'espressione è String, allora i confronti tra le stringhe sono svolti come specificato dal metodo String.equals, quindi in modo case sensitive.

#### Fall-through

Raggiunta una etichetta case ed eseguite le relative istruzioni, il flusso di esecuzione prosegue attraversando le etichette case seguenti, a meno che non incontri una istruzione break; (nel qual caso esce dallo switch). Nell'esempio riportato sopra, se il valore di espressione è uguale a espr_costante1, allora saranno eseguite le istruzioni di tutte le etichette case e anche dell'etichetta default.
Nella maggior parte dei casi, questo comportamento, perfettamente legittimo dal punto di vista del linguaggio, non era nelle intenzioni del programmatore che ha scritto il codice. Quindi, è buona norma
* apporre sempre il break; prima delle etichette case e default
* in caso contrario, segnalare con un commento che il break; è stato omesso intenzionalmente
Quindi, tipicamente, una istruzione switch ha la forma

## Strutture iterative
### while

Esegue una istruzione un numero arbitrario di volte, finché una certa espressione booleana restituisce true.
La condizione viene calcolata ogni volta prima di eseguire l'istruzione.

### do ... while

Esegue una istruzione un numero arbitrario di volte, finché una certa espressione booleana restituisce true.
La condizione viene calcolata ogni volta dopo che l'istruzione è stata eseguita.
A differenza del while, il do ... while esegue l'istruzione almeno una volta. In pratica, è equivalente a:

### for

Esegue una istruzione un numero arbitrario di volte, in funzione di una espressione booleana, e permette di indicare in un solo punto le variabili e le istruzioni che influenzano l'esecuzione del ciclo.
inizializzazione, condizione e passo sono facoltative; i punti e virgola che le separano sono obbligatori. La prima contiene una istruzione, oppure la dichiarazione di una o più variabili, e (se presente) viene eseguita una solta volta, all'entrata del for. La seconda è una espressione booleana, che viene calcolata ad ogni ciclo (se omessa, si assume true, il che risulta utile per scrivere in modo conciso un ciclo infinito). La terza contiene una istruzione che viene eseguita alla fine di ogni ciclo.
In definitiva, il for si comporta come il codice seguente:
Il vantaggio principale di mettere insieme inizializzazione, condizione e passo è la maggiore leggibilità del codice; inoltre, modificare le variabili e la condizione che controllano il ciclo è più semplice, in quanto la zona di codice interessata è circoscritta e in evidenza.

#### Scope delle variabili

Lo scope delle variabili definite nell'inizializzazione coincide con l'intera istruzione for (cioè comprende l'istruzione, la condizione e il passo); da ciò consegue che il seguente codice compila:

#### Uso tipico

In genere, viene usato dove ci sono una o più variabili che controllano l'andamento del ciclo. In genere, l'inizializzazione viene usata tipicamente per dichiarare le variabili e inizializzarle e il passo le modifica. Risulta molto comodo per iterare su array o oggetti contenitore (collezioni).
Un esempio con più di una variabile di controllo:
il cui output è:
in quanto la condizione di terminazione restituisce true con i < 10 e y > 16, ma alla quinta iterazione y = 16 e restituisce false terminando il ciclo.

### For each

Itera lungo un array o un oggetto di tipo java.lang.Iterable.

## Note

* ↑ Ciò si rende necessario per evitare il caso in cui due etichette diverse assumano un valore uguale a tempo di esecuzione; infatti, in questo caso, il flusso di esecuzione dovrebbe prendere due strade diverse, il che è impossibile. Al contrario, se tutte le espressioni sono costanti, il compilatore può controllare che siano anche diverse tra loro e, quindi, evitare questa situazione di ambiguità.

### Documentazione

* ↑ Metodo String.equals(Object)

### Approfondimenti

* ↑ Java Language Specification, 17.3
* ↑ Strings in switch Statements