Istruzione break in Java
- L'istruzione
break
interrompe immediatamente l'esecuzione di un ciclo o un blocco switch. - Può essere utilizzata in cicli (for, while) per prevenire ulteriori iterazioni quando una condizione viene soddisfatta.
- In cicli annidati, il
break
interrompe solo il ciclo più interno, a meno che non venga usato unbreak
etichettato. - Il
break
etichettato permette di uscire da più livelli di cicli o blocchi annidati, similmente a un goto controllato. - L'abuso della dichiarazione
break
può rendere il codice meno leggibile; è preferibile usare le normali condizioni dei cicli per il controllo del flusso.
Istruzioni di salto
Java supporta tre istruzioni di salto: break
, continue
e return
.
Queste istruzioni trasferiscono il controllo a un'altra parte del programma. In questa lezione ci concentreremo sull'istruzione break
. Le istruzioni continue
e return
sono trattate nelle prossime lezioni.
Gestione delle eccezioni come alternativa
Oltre alle istruzioni di salto qui trattate, Java offre un altro modo per modificare il flusso di esecuzione del programma: la gestione delle eccezioni.
La gestione delle eccezioni fornisce un metodo strutturato mediante il quale gli errori di run-time possono essere intercettati e gestiti dal programma. È supportata dalle parole chiave try
, catch
, throw
, throws
e finally
.
In sostanza, il meccanismo di gestione delle eccezioni consente al programma di effettuare un ramo non locale. Poiché la gestione delle eccezioni è un argomento ampio, lo tratteremo in dettaglio nelle lezioni successive.
L'istruzione break
In Java, l'istruzione break
ha tre impieghi:
- Come già visto, termina una sequenza di istruzioni in uno
switch
. - Può essere usata per uscire da un ciclo.
- Può fungere da forma migliorata di
goto
.
Avendo visto già il primo impiego, in questa lezione ci concentreremo sugli altri due.
Uso di break
per uscire da un ciclo
Mediante break
è possibile forzare l'interruzione immediata di un ciclo, ignorando l'espressione condizionale e qualsiasi codice rimanente nel corpo del ciclo.
Quando viene incontrata un'istruzione break
all'interno di un ciclo, il ciclo viene terminato e il controllo del programma riprende con l'istruzione successiva al ciclo.
Ecco un semplice esempio:
// Uso di break per uscire da un ciclo.
class InterrompiCiclo {
public static void main(String[] args) {
for (int indice = 0; indice < 100; indice++) {
if (indice == 10) break; // termina il ciclo se indice vale 10
System.out.println("indice: " + indice);
}
System.out.println("Ciclo completato.");
}
}
Questo programma produce il seguente output:
indice: 0
indice: 1
indice: 2
indice: 3
indice: 4
indice: 5
indice: 6
indice: 7
indice: 8
indice: 9
Ciclo completato.
Come si può vedere, sebbene il ciclo for
sia predisposto per l'esecuzione da 0 a 99, l'istruzione break
lo fa terminare anticipatamente, quando indice
vale 10.
L'istruzione break
può essere utilizzata con qualsiasi ciclo di Java, compresi i cicli intenzionalmente infiniti. Ad esempio, ecco il programma precedente riscritto mediante un ciclo while
. L'output di questo programma è lo stesso appena mostrato.
// Uso di break per uscire da un ciclo while.
class InterrompiCiclo2 {
public static void main(String[] args) {
int indice = 0;
while (indice < 100) {
if (indice == 10) break; // termina il ciclo se indice vale 10
System.out.println("indice: " + indice);
indice++;
}
System.out.println("Ciclo completato.");
}
}
Quando break
è usato all'interno di un insieme di cicli annidati, interrompe solo il ciclo più interno. Per esempio:
// Uso di break con cicli annidati.
class InterrompiCiclo3 {
public static void main(String[] args) {
for (int passaggio = 0; passaggio < 3; passaggio++) {
System.out.print("Passaggio " + passaggio + ": ");
for (int indiceInterno = 0; indiceInterno < 100; indiceInterno++) {
// termina il ciclo se indiceInterno vale 10
if (indiceInterno == 10) break;
System.out.print(indiceInterno + " ");
}
System.out.println();
}
System.out.println("Cicli completati.");
}
}
Questo programma genera il seguente output:
Passaggio 0: 0 1 2 3 4 5 6 7 8 9
Passaggio 1: 0 1 2 3 4 5 6 7 8 9
Passaggio 2: 0 1 2 3 4 5 6 7 8 9
Cicli completati.
Come si può notare, l'istruzione break nel ciclo interno provoca la terminazione solo di quel ciclo. Il ciclo esterno rimane inalterato.
Vi sono altri due aspetti da ricordare riguardo a break
:
- In un ciclo possono comparire più istruzioni
break
; tuttavia è opportuno fare attenzione, poiché un numero eccessivo dibreak
tende a destrutturare il codice. - Il
break
che termina un'istruzioneswitch
influisce solo su quelloswitch
e non su eventuali cicli racchiudenti.
Cercare di non abusare dell'istruzione break
break
non è stato progettato come mezzo normale per terminare un ciclo. A tale scopo serve l'espressione condizionale del ciclo. L'istruzione break
andrebbe utilizzata per annullare un ciclo solo quando si verifica una situazione particolare.
Uso di break
come forma di goto
Oltre ai suoi utilizzi con l'istruzione switch
e con i cicli, l'istruzione break
può anche essere impiegata da sola per offrire una forma migliorata dell'istruzione goto
.
Java non possiede l'istruzione goto
perché essa consente di ramificare in modo arbitrario e non strutturato, rendendo di solito il codice pieno di goto
difficile da comprendere e da mantenere, oltre a impedire alcune ottimizzazioni del compilatore.
Esistono tuttavia pochi casi in cui il goto
rappresenta un costrutto valido e legittimo per il controllo di flusso. Per esempio, un goto
può essere utile quando occorre uscire da un insieme profondamente annidato di cicli. Per gestire tali situazioni, Java definisce una forma estesa dell'istruzione break
. Utilizzando questa forma di break
è possibile, per esempio, uscire da uno o più blocchi di codice. Questi blocchi non devono far parte di un ciclo o di uno switch
; possono essere qualsiasi blocco.
Inoltre, è possibile specificare con esattezza dove riprenderà l'esecuzione, poiché questa forma di break
funziona con un'etichetta. In tal modo, break
offre i vantaggi di un goto
senza i relativi problemi.
La forma generale di un'istruzione break
etichettata è mostrata qui:
break etichetta;
Nella maggior parte dei casi, etichetta
è il nome di un'etichetta che identifica un blocco di codice.
Può essere un blocco autonomo, ma può anche essere il blocco bersaglio di un'altra istruzione. Quando questa forma di break
viene eseguita, il controllo viene trasferito fuori dal blocco etichettato.
Il blocco etichettato deve racchiudere l'istruzione break
, ma non è necessario che sia il blocco immediatamente più interno. Ciò significa, per esempio, che si può usare un break
etichettato per uscire da una serie di blocchi annidati. Non è invece possibile usare break
per trasferire il controllo fuori da un blocco che non racchiude l'istruzione break
.
Per assegnare un nome a un blocco, bisogna porre un'etichetta all'inizio del blocco stesso. Un'etichetta è un qualsiasi identificatore Java valido seguito da due punti.
Una volta etichettato un blocco, si può usare tale etichetta come bersaglio di un'istruzione break
. In tal modo l'esecuzione riprende alla fine del blocco etichettato. Per esempio, il programma seguente mostra tre blocchi annidati, ciascuno con la propria etichetta. L'istruzione break
fa avanzare l'esecuzione oltre la fine del blocco etichettato secondo
, saltando le due istruzioni println()
.
// Uso di break come forma civilizzata di goto.
class Interrompi {
public static void principale(String[] argomenti) {
boolean vero = true;
primo: {
secondo: {
terzo: {
System.out.println("Prima dell'interruzione.");
if (vero) break secondo; // esce dal blocco secondo
System.out.println("Questo non verrà eseguito");
}
System.out.println("Questo non verrà eseguito");
}
System.out.println("Questo è dopo il blocco secondo.");
}
}
}
Esecuzione del programma:
Prima dell'interruzione.
Questo è dopo il blocco secondo.
Uno degli usi più comuni di un break
etichettato è l'uscita da cicli annidati. Nel programma seguente, per esempio, il ciclo esterno viene eseguito una sola volta:
// Uso di break per uscire da cicli annidati.
class InterrompiCiclo4 {
public static void principale(String[] argomenti) {
esterno: for (int passaggio = 0; passaggio < 3; passaggio++) {
System.out.print("Passaggio " + passaggio + ": ");
for (int indiceInterno = 0; indiceInterno < 100; indiceInterno++) {
if (indiceInterno == 10) break esterno; // esce da entrambi i cicli
System.out.print(indiceInterno + " ");
}
System.out.println("Questo non verrà stampato");
}
System.out.println("Cicli completati.");
}
}
Questo programma produce il seguente output:
Passaggio 0: 0 1 2 3 4 5 6 7 8 9 Cicli completati.
Come si può notare, quando il ciclo interno esegue il break
verso il ciclo esterno, entrambi i cicli vengono terminati. Si osservi che in questo esempio viene etichettato l'istruzione for
, che possiede un blocco di codice come bersaglio.
È importante ricordare che non è possibile eseguire un break
verso un'etichetta che non sia definita per un blocco racchiudente. Il programma seguente, per esempio, è errato e non viene compilato:
// Questo programma contiene un errore.
class InterrompiErr {
public static void principale(String[] argomenti) {
uno: for (int passaggio = 0; passaggio < 3; passaggio++) {
System.out.print("Passaggio " + passaggio + ": ");
}
for (int indiceInterno = 0; indiceInterno < 100; indiceInterno++) {
if (indiceInterno == 10) break uno; // ERRATO
System.out.print(indiceInterno + " ");
}
}
}
Poiché il ciclo etichettato uno
non racchiude l'istruzione break
, non è possibile trasferire il controllo fuori da quel blocco.