Semantica Operazionale di un frammento di Java

Eccezioni in Java
1
Ricordiamo che
 una procedura può terminare
– normalmente, ritornando un risultato
– in modo eccezionale
• ci possono essere diverse terminazioni eccezionali
• in Java, corrispondono a diversi tipi di eccezioni
• il nome del tipo di eccezione fornisce informazione sulla
natura del problema
 Esistono eccezioni predefinite
 Ma si possono anche definire nuove eccezioni per
segnalare situazioni particolari
2
Vedremo
 Come si lanciano eccezioni
 Come si gestiscono le eccezioni (Un
programma ben scritto dovrebbe prevedere tali eventualità
inserendo delle istruzioni per individuare le anomalie e
ripristinare una situazione corretta)
 Vedremo poi in MP il ruolo e l’utilita’ delle
eccezioni (che non indicano solo e
necessariamente errori)
3
Le eccezioni in Java
 i tipi di eccezione sono particolari classi che
– contengono solo il costruttore
• ci possono essere più costruttori overloaded
– sono definite in “moduli” separati da quelli che contengono i
metodi che le possono sollevare
 le eccezioni sono oggetti
– creati eseguendo new di un exception type
• e quindi eseguendo il relativo costruttore
 esiste una gerarchia “predefinita” di tipi relativi
alle eccezioni
– nuovi tipi di eccezioni sono collocati nella gerarchia
con l’usuale extends
4
La gerarchia di tipi per le
eccezioni
Throwable
Error
Exception
RuntimeException
 se un tipo di eccezione estende la classe Exception
– l’eccezione è checked
 se un tipo di eccezione estende la classe
RuntimeException
– l’eccezione è unchecked
5
Eccezioni Primitive
– IndexOutOfBoundsException
E’ una eccezione unchecked, indica l’accesso ad un elemento
inesistente di un array
– NullPointerException
E’ una eccezione unchecked, indica l’accesso ad un oggetto
indefinito
6
Altri Errori
 Errori di Cast
 Tentativi di accedere a file inesistenti;
 Fine inaspettata di un file durante la lettura;
 Errore hardware accedendo a un disco;
 Chiusura inattesa di una connessione remota...
7
Differenza checked e unchecked
 se una procedura può sollevare una eccezione
checked
– deve elencarla nel suo header
• altrimenti si verifica un errore a tempo di compilazione
 se una procedura può sollevare una eccezione
unchecked
– può non elencarla nel suo header
• Si puo’ comunque elencarla sempre per chiarezza
8
Sintassi della clausola throws
<modificatori> <tipo> <nome-metodo> (<listaparametri>) throws <Classe-ecc1>, ...,
<Classe-eccN> { <corpo-metodo>
}
 La clausola throws viene inserita nella dichiarazione del metodo per
informare il compilatore che durante l'esecuzione di quel metodo
possono essere generate eccezioni dei tipi elencati dopo la parola
chiave throws, la cui gestione viene delegata al chiamante.
 Quelle checked devono essere obbligatoriamente riportate nell’header
9
Gestione delle Eccezioni
 Cosa succede quando un metodo termina sollevando
un’eccezione?
 L’eccezione viene passata al metodo chiamante
 Per default, un metodo che riceve un'eccezione termina
l'esecuzione e passa l'eccezione al metodo chiamante.
 Quando l'eccezione raggiunge main, l'esecuzione del
programma termina stampando un opportuno messaggio di
errore.
10
Esempio:riferimento null
public class NestedNullPointer {
public static void bar(){
Object o = null;
System.out.println(o.toString());
}
public static void foo(){
bar();
}
public static void main(String [] args){
foo();
}
}
11
Esecuzione


java NestedNullPointerException
in thread "main" java.lang.NullPointerException
at NestedNullPointer.bar(NestedNullPointer.java:4)
at NestedNullPointer.foo(NestedNullPointer.java:7)
at NestedNullPointer.main(NestedNullPointer.java:10)
 Tutti i metodi annidati terminano
 Viene elencata la catena dei metodi attivi nel momento in
cui si verifica l'eccezione (bar - foo - main) e per ogni
metodo la linea di codice dove si è verificata.
12
Esempio:Outof Bounds
public class OutOfBounds {
public static void main(String [] args){
int [] array = new int [5];
for (int i = 0; i < array.length; i++) {
array[i] = (int) (100 * Math.random());
}
System.out.println("Contenuto dell'array:");
// Errore nella guardia del for
for (int i = 0; i <= array.length; i++) {
System.out.println(array[i]);
}
}
}
13
Alternativa: Gestione Esplicita
Il chiamante puo’
– gestione di default, mediante propagazione dell’eccezione alla
procedura chiamante
• possibile solo per eccezioni non checked o per eccezioni checked elencate
nell’header della procedura che riceve l’eccezione
– gestione esplicita (mediante try and catch)
• in generale, quando si ritiene di poter recuperare uno stato
consistente e di portare a termine una esecuzione quasi
“normale”
14
Catturare una Eccezione
 Il codice che potrebbe sollevare l’eccezione e’ racchiuso
all’interno di uno statement try
 Il codice per gestire l’eccezione e’ racchiuso all’interno di
uno statement catch
15
Sintassi: forma semplificata
try {
<istruzioni-try>;
// possono lanciare delle eccezioni
}
catch(<sottoclasse-Throwable> e1) {;
// catturiamo l'eccezione e1 di tipo
<sottoclasse-Throwable>
<istruzioni-catch>; // gestiamo e1
}
16
Semantica
Si eseguono le <istruzioni-try>.
•Se l'esecuzione termina senza fallimenti si prosegue ad
eseguire la prima istruzione successiva al blocco try-catch.
•Altrimenti, se l'esecuzione di <istruzioni-try> lancia
un'eccezione except che e’ sottotipo di <sottoclasse-Throwable>
si eseguono le <istruzioni-catch> . Infine si prosegue ad
eseguire la prima istruzione successiva al blocco try-catch.
•Altrimenti, se l’eccezione non e’ sottotipo di
<sottoclasse-Throwable> il metodo si comporta come se
non ci fosse try-catch (l’eccezione viene passata al metodo chiamante
17
Esempio: termina normalmente
public class CatchOutOfBounds {
public static void main(String [] args) {
int [] array = new int [5];
for (int i = 0; i < array.length; i++) {
array[i] = (int) (100 * Math.random());
}
System.out.println("Contenuto dell'array:");
try {
int i = 0;
while (true) // ciclo infinito
// ben presto i oltrepassera' il limite dell'array
System.out.println(array[i++]);
}
// catch (Throwable e) {
catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Stampa terminata...");
}
}
}
18
Esempio
Supponiamo di avere in una classe Num una procedura
statica con la seguente specifica
public static int fact (int n) throws NonpositiveExc
// EFFECTS: se n>0, ritorna n!
// altrimenti solleva NonpositiveExc
L’eccezione viene utilizzata per indicare un risultato
particolare (invece di fornire un risultato particolare)
19
Esempio
try { x = Num.fact (y); }
catch (NonPositiveExc e) {
// qui possiamo usare e, cioè l’oggetto eccezione
String s = e.toString() ;
System.out.println(s)
}
Nel catch e’ contenuto il codice per gestire l’eccezione
Il programma termina normalmente scrivendo il contenuto
dell’eccezione (una spiegazione di cosa e’ successo)
20
Esempio sugli arrays
public static int search (int[] a, int x) throws
NullPointerExc, NotFoundExc
// EFFECTS: se a è null solleva NullPointerExc
// se x non occorre in a solleva NotFoundexc
// altrimenti ritorna un indice in cui occorre
Una procedura stand-alone di una classe Arrays, usa eccezioni
diverse per segnalare situazioni particolari
21
Un metodo che la usa
 la clausola catch non deve necessariamente identificare il
tipo preciso dell’eccezione, ma basta un suo supertipo,
principio di sostituzione
try { x = Arrays.search (v, y); }
catch (Exception e) { s.Println(e); return;}
// s è una PrintWriter
 segnala l’informazione sia su NullPointerExc che su
NotFoundExc, eccezioni sollevate da searchsorted
22
Try e Catch annidati
try { ...;
try { x = Arrays.search (v, y); }
catch (NullPointerExc e) {
throw new NotFoundExc ();}
}
catch (NotFoundExc b ) {...}
 la clausola catch nel try più esterno cattura l’eccezione
NotFoundExc se è sollevata da searchSorted o dalla
clausola catch più interna
 l’eccezione NullPointerExc non è visibile da fuori
23
Definire nuovi tipi di eccezione
public class NuovoTipoDiEcc extends Exception {
public NuovoTipoDiEcc(String s) {super(s);}
}
 è checked (analogo per unchecked)
 definisce solo un costruttore
 il corpo del costruttore riutilizza semplicemente il
costruttore del supertipo
– perché deve passargli il parametro
 una new di questa classe provoca la creazione di un nuovo
oggetto che “contiene” la stringa passata come parametro
24
Costruire oggetti eccezione
 una new di questa classe provoca la creazione di un nuovo
oggetto che “contiene” la stringa passata come parametro
Exception e = new NuovoTipoDiEcc (“Questa è la
ragione”) ;
String s = e.toString() ;
 la variabile s punta alla stringa
“NuovoTipoDiEcc: Questa è la ragione”
25
Lanciare una eccezione: throw
 una procedura può terminare
– (ritorno normale) con un return
– (ritorno di una eccezione) con un throw
public static int fact (int n) throws NonpositiveExc
// EFFECTS: se n>0, ritorna n!
// altrimenti solleva NonpositiveExc
{ if (n <= 0) throw new NonPositiveExc(“Num.fact”);
...}
 la stringa contenuta nell’eccezione è utile soprattutto
quando il programma non è in grado di “gestire”
l’eccezione
– permette all’utente di identificare la procedura che la ha sollevata
– può comparire nel messaggio di errore che si stampa subito prima
di forzare la terminazione dell’esecuzione
26
Nel Corso di Metodologie
 Vedremo il ruolo delle Eccezioni (checked e
unchecked)
 Esercizio: per imparare a gestirlo
 Tabelle (Frames) con le Eccezioni
 Main che le gestisce……
27