350 likes | 523 Views
Gestione delle eccezioni. Percorso. Eventi eccezionali Identificazione, descrizione e segnalazione Eccezioni in Java I meccanismi offerti Le classi principali Modellare le eccezioni. Affidabilità di un programma. Un programma esegue una sequenza di operazioni su un calcolatore
E N D
Percorso • Eventi eccezionali • Identificazione, descrizione e segnalazione • Eccezioni in Java • I meccanismi offerti • Le classi principali • Modellare le eccezioni
Affidabilità di un programma • Un programma esegue una sequenza di operazioni su un calcolatore • Alcune direttamente, altre attraverso le funzionalità offerte dal sistema operativo • Talvolta qualche operazione non può essere effettuata • Il programma deve accorgersene e reagire di conseguenza
Le ragioni del fallimento • Mancanza di risorse • Memoria esaurita, disco pieno, autorizzazioni insufficienti, … • Parametri errati • Divisione per 0, riferimenti a risorse inesistenti (file, URL), … • Sequenza illecita di operazioni • Utilizzo di riferimenti nulli, scrittura su file chiuso, …
Le ragioni del fallimento • Alcune dipendono dal programmatore • Altre, dal contesto di esecuzione • In ogni caso, quando si rileva un’anomalia • Non è possibile concludere l’operazione in corso • Il programma, nel suo complesso, viene a trovarsi in uno stato incoerente • Per garantire l’affidabilità del sistema, occorre mettere in atto una strategia di rilevazione e gestione delle eccezioni
Strategie • Tutte le operazioni che possonofallire, devono indicare: • Se sono terminate con successo o meno • L’eventuale anomalia riscontrata • Alcuni linguaggi si basano su valori di ritorno • Occorre verificarli • Il diagramma di flusso si complica notevolmente • Se si omette un test, si compromette la capacità di valutare l’integrità del sistema
Semplice procedura: Tre operazioni in successione Ciascuna può fallire Esempio Apri il file Scrivi Chiudi il file
no si no si no si OK? OK? OK? Esempio Scrivi Chiudi il file Apri il file
Complessità • Rapidamente, il codice associato ad una procedura semplice diventa ingestibile • La reazione comune consiste nell’omettere i test • Cosa fare quando si rileva un malfunzionamento?
Contesto • Spesso, ci si accorge dei fallimenti all’interno di procedure generiche • Non si sa quali contromisure prendere • Occorrerebbe segnalare il malfunzionamento al chiamante • Fornendo la descrizione più accurata possibile di quanto successo • Il chiamante può gestire l’eccezione o rimandarne la gestione al proprio chiamante, ricorsivamente…
La risposta di Java • Un’insieme di classi per modellare l’anomalia riscontrata • Fa capo alla classe Throwable • Meccanismi per • Segnalare • Gestire • Propagare un’anomalia, attraverso la catena di invocazione dei metodi
Sintassi • Un metodo che può fallire deve segnalarlo nella propria dichiarazione • Attraverso la parola chiave “throws” • Seguita dal tipo (o dai tipi) di eccezione che si può verificare durante l’esecuzione • Chi invoca tale metodo deve: • Cercare di gestire la possibile anomalia attraverso il costrutto “try” / “catch” • Oppure, segnalare che a propria volta può generare la stessa anomalia: l’eccezione si propaga al chiamante del chiamante
Segnala che puo’ fallire Verifica la coerenza Descrive l’anomalia Interrompe l’esecuzionedel metodo Esempio double div(int num, int den)throwsException { if (den==0) throw newException(“div 0”); return num/den; }
Try/Catch • Costrutto utilizzato per il controllo delle eccezioni • Isola le parti di codice che possono provocare anomalie try{ … // codice da controllare }catch(…Exception e){ … // gestione anomalia }
Try/Catch • È possibile reagire in modo differente a tipi diversi di eccezioni mettendo più clausole “catch” in sequenza • Avendo cura di indicare dapprima le anomalie più specifiche try{ … }catch(ExceptionA e1){ … }catch(ExceptionB e2){ … }
La clausola “finally” • finally indica le istruzioni che devono essere eseguite comunque • Tanto nel caso in cui il codice controllato sia stato eseguito correttamente • Quanto nel caso in cui si sia verificata un’eccezione try{ … // codice da controllare }catch(Exception e){ … // gestione dell’anomalia }finally{ … // istruzioni da eseguire // in ogni caso }
1) Qualunque anomalia in questo blocco determina l’interruzione dell’esecuzione try{ … … }catch(ExcA e1){ … } catch(ExcB e2){ … } finally{ … }
2) Si confronta il tipo segnalato con quelli indicati nelle clausole “catch”: si seleziona la prima corrispondenza trovata try{ … … }catch(ExcA e1){ … } catch(ExcB e2){ … } finally{ … }
3) Si esegue il blocco di codice corrispondente: la segnalazione dell’anomalia viene rimossa try{ … … }catch(ExcA e1){ … } catch(ExcB e2){ … } finally{ … }
4) Comunque siano andate le cose, viene eseguito il blocco “finally”, se presente try{ … … }catch(ExcA e1){ … } catch(ExcB e2){ … } finally{ … }
Problemi • Il codice del blocco catch selezionato dovrebbe ripristinare la coerenza nel sistema • Non è detto sia possibile! • È possibile che si verifichi un’eccezione durante l’esecuzione del blocco catch • Può dare origine ad una struttura di programmazione alquanto complessa • Può essere indice di cattiva progettazione
Gestire le eccezioni • Stampare un messaggio di errore • Non risolve nulla, ma aiuta il debugging try{ … }catch(Exception e1){ e1.printStackTrace(); }
Gestire le eccezioni • Generare una nuova eccezione • Permette di aggiungere informazioni sul contesto in cui si è verificata l’anomalia originale try{ … }catch(Exception e1){ thrownew MyExc(e1,new Date()); }
Gestire le eccezioni • Rilanciare la stessa eccezione • Avendo compiuto qualche azione a margine try{ … }catch(Exception e1){ Logger.log(e1.getMessage());throwe1; }
Gestire le eccezioni • Correggere l’anomalia… • ...e riprovare l’azione • Facendo attenzione ai cicli infiniti boolean done = false; do { try{ … ; done = true; } catch(Exception e1){ //correggi l’anomalia … } while(! done);
Gestire le eccezioni • Ripristinare uno stato precedente… • …disfacendo eventuali azioni non terminate (rollback) ContoCorrente a,b; //… int stato =0; double somma; try { a.preleva(somma); stato = 1; b.deposita(somma); stato = 2; } catch(Exception e1){ if (stato == 1) a.deposita(somma); }
Gestire le eccezioni • Interrompere l’esecuzione • Disastro irreparabile! try{ … }catch(Exception e1){ System.exit(0); }
Gestire le eccezioni • Non fare nulla • La peggior scelta possibile! • Da non fare mai try{ … }catch(Exception e1){ //nessuna azione! }
Modellare le eccezioni • Java prevede che un’anomalia sia descritta da un oggetto di tipo Throwable • Classe radice della gerarchia delle eccezioni • Offre vari metodi per la gestione dell’anomalia • Le sue sottoclassi modellano diversi tipi di malfunzionamenti
La classe Throwable • String getMessage() • Restituisce la stringa che descrive l’anomalia • Inizializzata nel costruttore a partire da un parametro • void printStackTrace() • Stampa la posizione in cui si è verificata l’eccezione e la sequenza dei metodi chiamanti ad essa relativi • Riporta anche, se disponibili, i riferimenti alle righe, nei file sorgente, in cui si sono verificate le successive invocazioni
Tipologie di anomalie • Errori della macchina virtuale • Fanno capo alla classe Error • Non possono essere recuperati • Memoria esaurita, stack overflow, … • Errori di programma • Fanno capo alla classe Exception • Per lo più, devono essere gestiti in modo esplicito, dichiarandone l’eventualità nei metodi che li possono generare e utilizzando costrutti di tipo “try” • Alcuni possono capitare pressoché sempre (RuntimeException): non occorre dichiarare esplicitamente la possibilità che si verifichino
unrecoverable problems ‘unchecked’ exceptions Throwable Error Exception Stack Overflow RuntimeException ‘checked’ exceptions NullPointerException IOException Gerarchia delle eccezioni
Definire nuove eccezioni • È possibile creare classi di eccezioni personalizzate • Spesso non contengono nessun metodo né attributo • Di solito, hanno un costruttore anonimo, che associa all’oggetto una descrizione generica ed un costruttore che accetta una stringa, che permette di dettagliare l’anomalia verificatasi
Esempio public class MyException extends Exception { public MyException() { super(“MyException”); } public MyException(String s){ super(“MyException: ”+s); } } … throw new MyException(“message”); …