eccezioni

gestione di situazioni fuori dalla norma

Legge di Murphy: se qualcosa può andar male, lo farà.

Durante la costruzione (e l'uso) dei programmi succede più spesso di quanto vorremmo di vedere delle "scritte rosse" nella console di eclipse. Scritte che servono per trovare gli errori a chi scrive il programma ma che aiutano ben poco chi il programma lo usa!

Prendiamo per esempio questo programma che dovrebbe calcolare il doppio di una numero. Cosa succede se l'utente scrive "ciao" nella prima casella?

public class EccezioniEsecizio1 extends Application {
	TextField cDato = new TextField("numero");
	TextField cRisposta = new TextField("");

	public void start(Stage primaryStage) {		
		Button pDoppio = new Button("doppio");
		GridPane p = new GridPane();
		p.add(cDato, 0, 0);
		p.add(pDoppio, 0, 1);
		p.add(cRisposta, 0, 2);
		pDoppio.setOnAction( e -> scambia() );
		Scene scena = new Scene(p);
		primaryStage.setTitle("Doppio");
		primaryStage.setScene(scena);
		primaryStage.show();
	}

	public void scambia() {
		String testo;
		int numero,doppio;
		testo = cDato.getText();
		numero = Integer.parseInt(testo);
		doppio = numero * 2;
		cRisposta.setText(""+doppio);
	}
	
	public static void main(String args[]){
		launch();
	}
}

Semplice: il programma non funziona e nella console di eclipse vediamo:

Exception in thread "JavaFX Application Thread" java.lang.NumberFormatException: For input string: "ciao"

NumberFormatException è il nome di una eccezione che rappresenta un problema con il numero da convertire ma ne esistono molte altre.

Una eccezione è un particolare oggetto che estende java.lang.Exception e che rappresenta un problema che insorge a tempo di esecuzione.

Esiste un modo per controllare cosa fare in caso si presenti una situazione del genere. Quello che ci serve è un costrutto sintattico chiamato try-catch che nella sua forma più semplice si usa così:

try{
  /* parte di codice che può creare problemi */
}catch( tipo_dell_eccezione nome){
  /* codice per gestire l'eccezione */
}

Se la parte del codice racchiusa nel try fosse composta da 10 linee e l'eccezione venisse sollevata dalla prima linea le restanti 9 non verrebbero eseguite e il programma passerebbe alla parte dentro al catch (se l'eccezione è del tipo giusto).

Nel caso dell'esempio sopra tipo_dell_eccezione cosa sarebbe?

NumberFormatExceptiongiusto! è il nome della classe che viene visualizzato nella console sulla prima riga java.langquesto è il pacchetto a cui appartiene l'eccezione ciaoquesta è la stringa che ha causato l'eccezione

In pratica quello che dobbiamo fare è sostituire una parte del nostro codice:

public void scambia() {
  String testo;
  int numero,doppio;
  testo = cDato.getText();
  try{
    numero = Integer.parseInt(testo);
    doppio = numero * 2;
    cRisposta.setText(""+doppio);
  }catch(NumberFormatException e){
    cRisposta.setText("hai scritto male il numero");
  }
}

Perché nel try non c'è soltanto la linea numero = Integer.parseInt(testo);?

le altre andava bene anche metterle dopo la "}" del catch no, se numero non può essere calcolato non ha senso neanche calcolare il doppio se non funziona quella le altre non potrebbero fare nulla giusto! se questa va male le altre non possono essere eseguite

È possibile anche che più di una cosa vada male... in questo caso posso mettere più catch:

try{
  /* parte di codice che può creare problemi */
}catch( tipo_dell_eccezione_1 nome){
  /* codice per gestire il problema del primo tipo */
}catch( tipo_dell_eccezione_2 nome){
  /* codice per gestire l'eccezione del secondo tipo */
}

Una ultima considerazione: non tutte le eccezioni sono uguali... alcune eccezioni devono obbligatoriamente essere gestite dal programma altre no!

Quali eccezioni devono essere gestite esplicitamente dal programma?

NumberFormatException no, finora non l'abbiamo gestita e il compilatore non si è lamentato ArithmeticException no, è l'eccezione che viene sollevata quando ad esempio si divide per zero, finora non l'abbiamo gestita e il compilatore non si è lamentato FileNotFoundException giusto!

La regola da applicare è questa: una eccezione va sempre gestita (con throws o try-catch) a meno che non ereditino da java.lang.RuntimeException, in questo caso non è obbligarorio farlo (e vengono chiamate unchecked exceptions).