Laboratorio di reti I Stefano Brocchi [email protected] 13 ottobre, 2009 Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 1 / 27 Introduzione Obiettivi del corso Aspetti di programmazione Java necessari alla programmazione di reti Sviluppo di applicazioni di rete basate su tecnologia Java Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 2 / 27 Introduzione Perchè Java ? Portabilità JVM Primitive orientate alla rete Semplice accesso alla rete Multithreading Remote Method Invocation Integrazione con la rete Applet Servlet Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 3 / 27 Introduzione Programma del corso Concetti base di Java Gestione degli errori tramite le eccezioni Comunicazione: il pacchetto java.io Multithreading Programmazione di reti Il pacchetto java.net Il linguaggio HTML Le applet ...? Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 4 / 27 Introduzione Riferimenti bibliografici Slide del corso http://www.dsi.unifi.it/users/brocchi/labreti/insegnamento.php.htm (modulo 1) http://www.dsi.unifi.it/users/brocchi/labreti/insegnamento2.php.htm (modulo 2) Thinking in Java, Bruce Eckel, distribuzione gratuita in rete della terza edizione Java Network Programming, Hughes et al., Manning Manuale pratico di Java, L. Bettini et al., HOPS Javadocs in rete (http://java.sun.com/javase/6/docs/api/) Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 5 / 27 Introduzione Modalità di esame Progetto: sviluppare una piccola applicazione di rete Discussione del progetto e orale Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 6 / 27 Le eccezioni Le eccezioni Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 7 / 27 Le eccezioni La problematica degli errori E’ necessario gestire situazioni dove il flusso del programma non può procedere normalmente Es. Divisione per zero, apertura di un file inesistente Problema: spesso il contesto non dispone di abbastanza informazioni per poter gestire l’errore Soluzione: rimandare il problema all’ambiente chiamante Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 8 / 27 Le eccezioni Le eccezioni Un approccio utilizzato (linguaggio C) è quello di ritornare un particolare valore in caso di errore Ogni chiamata a procedura dovrebbe essere seguita da un controllo di correttezza: codice poco chiaro Condizioni di errore spesso ignorate Approccio Java: ogni errore viene rappresentato tramite un oggetto di tipo (o figlio di) Exception In caso di una situazione di errore il metodo termina lanciando un’eccezione invece di restituire il valore di ritorno standard Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 9 / 27 Le eccezioni Lanciare un’eccezione Lanciare un’eccezione Un’eccezione ha due costruttori di default, uno vuoto ed uno che prende una stringa come parametro Exception e = new Exception(); Exception e2 = new Exception("Messaggio di errore"); Il lancio di un’eccezione avviene tramite la parola chiave throw if (t == null) { throw new NullPointerException("T is null !"); } Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 10 / 27 Le eccezioni Lanciare un’eccezione Gerarchia delle eccezioni Esiste una vasta gerarchia di eccezioni in Java per i molteplici tipi di errore. Object ClassNotFoundException IllegalArgumentException IllegalAccesException IndexOutOfBoundsException RuntimeException NullPointerException IOException FileNotFoundException Throwable Exception MalformedURLException Figure: Gerarchia di alcune eccezioni in Java Rivestono una particolare importanza le classi RuntimeException e le sue derivate Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 11 / 27 Le eccezioni Propagare un’eccezione Propagare un’eccezione Dopo l’esecuzione del comando throw la normale esecuzione del codice si interrompe Un metodo contenente codice che può lanciare un’eccezione ha due possibilità: gestirla o propagarla all’ambiente chiamante Nel caso in cui il metodo propaghi l’eccezione al chiamante occorre specificare questa possibilità nella firma del metodo tramite la clausola throws public int MyMethod() throws IOException { if (...) { throw new IOException(); } ... } Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 12 / 27 Le eccezioni Propagare un’eccezione Propagare un’eccezione - eccezioni runtime Fanno eccezione le eccezioni di tipo runtime (derivate da RuntimeException) dove la clausola throws non deve essere necessariamente specificata public int MyRuntimeMethod() { if (...) { throw new RuntimeException(); } ... } Se cosı̀ non fosse alcune eccezioni, come la NullPointerException, dovrebbero essere dichiarate nella clausola throws di quasi ogni metodo Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 13 / 27 Le eccezioni Propagare un’eccezione Propagare un’eccezione Dal momento in cui un metodo può sollevare un’eccezione tutti gli altri metodi che ne fanno uso devono a loro volta gestire o propagare l’eccezione. public int MyMethod2() throws IOException { MyMethod(); ... } Se nessun metodo gestisce l’eccezione questa risale per tutto lo stack delle chiamate fino ad arrivare alla JVM che termina l’esecuzione e stampa il contenuto dello stack. Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 14 / 27 Le eccezioni Propagare un’eccezione Propagare un’eccezione - esempio Per esempio eseguendo la seguente classe... public class propException { public static void b() throws Exception { throw new Exception("Eccezione di prova"); } public static void a() throws Exception { b(); } public static void main (String[] args) throws Exception { a(); } } Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 15 / 27 Le eccezioni Propagare un’eccezione Propagare un’eccezione - esempio ... si ottiene il seguente messaggio di errore Exception in thread "main" java.lang.Exception: Eccezione di prova at propException.b(propException.java:3) at propException.a(propException.java:6) at propException.main(propException.java:10) Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 16 / 27 Le eccezioni Gestire le eccezioni Gestire le eccezioni La gestione delle eccezioni avviene tramite il costrutto try...catch try { // Codice che può generare eccezioni } catch (TipoEccezione e) { // Codice per gestire l’eccezione } Se un’istruzione nel blocco try genera un’eccezione del tipo specificato nel catch l’esecuzione passa immediatamente alle istruzioni nel blocco catch Le istruzioni nel blocco catch possono utilizzare l’oggetto eccezione generato (nell’esempio e) Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 17 / 27 Le eccezioni Gestire le eccezioni Metodi di Exception Alcuni metodi utili della classe Exception: public void printStackTrace() public void printStackTrace(PrintStream s) Stampa una descrizione di dove l’eccezione è stata generata e dei punti dove è stata propagata public String getMessage() Restituisce il messaggio associato all’eccezione Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 18 / 27 Le eccezioni Gestire le eccezioni Gestire le eccezioni Se il codice nel corpo del try può generare diversi tipi di eccezione si possono inserire più clausole catch: try { // Codice che può generare eccezioni } catch (FileNotFoundException e1) { // Codice per gestire una FileNotFoundException } catch (NullPointerException e2) { // Codice per gestire una NullPointerException } catch (IndexOutOfBoundsException e3) { // Codice per gestire una IndexOutOfBoundsException } Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 19 / 27 Le eccezioni Gestire le eccezioni Gestire le eccezioni Se un’eccezione che viene sollevata è compatibile con più clausole catch il codice ad essere eseguito è quello del primo catch incontrato partendo dall’alto try { ... } catch (FileNotFoundException e1) { // Codice per gestire una FileNotFoundException } catch (IOException e2) { // Codice per gestire una IOException // che non sia una FileNotFoundException } catch (Exception e3) { // Codice per gestire una Exception // che non sia una IOException } Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 20 / 27 Le eccezioni Gestire le eccezioni Rilanciare le eccezioni Talvolta può capitare di voler gestire alcune eccezioni e di volerne invece propagare altre. Questo si può ottenere utilizzando sia costrutti try...catch sia istruzioni throw try { ... } catch (FileNotFoundException e1) { // Gestione della FileNotFoundException } catch (IOException e2) { ... throw e2; // L’eccezione viene ’rilanciata’ // al metodo chiamante } Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 21 / 27 Le eccezioni Gestire le eccezioni Il blocco finally E’ possibile specificare tramite il blocco finally delle istruzioni che saranno eseguite comunque, che un’eccezione si verifichi o no. try { ... } catch (FileNotFoundException e) { ... } finally { // Codice che verrà comunque eseguito } Utile per rilasciare delle risorse acquisite (per esempio per chiudere una connessione) Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 22 / 27 Le eccezioni Estendibilità Eccezioni ed estendibilità Riscrivendo un metodo con clausole throws in una sottoclasse è proibito lanciare eccezioni che non potevano essere lanciate dal metodo della sovraclasse In questo modo sostituendo un oggetto ad uno meno specializzato tutto continua a funzionare correttamente (principio della programmazione ad oggetti) E’ possibile creare le proprie eccezioni estendendo la classe Exception o le sue derivate Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 23 / 27 Le eccezioni Eccezioni checked ed unchecked Eccezioni checked e unchecked Tutte le eccezioni di tipo diverso da RuntimeException si dicono checked, in quanto la loro gestione deve essere gestita esplicitamente Se un’eccezione non viene gestita ed il metodo non ne dichiara la propagazione si ottiene un errore in fase di compilazione: Java cerca di costringerci a creare del codice robusto Evitare assolutamente di far sparire le eccezioni: try { ... } catch (Exception e) { } Le eccezioni a runtime si dicono invece unchecked e sfuggono a questo meccanismo di controllo in fase di compilazione Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 24 / 27 Le eccezioni Esercizio Esercizio Scrivere una classe che, ricevendo in ingresso una lista di interi come parametri, stampi il risultato della divisione intera del primo per il secondo, del terzo per il quarto, e cosı̀ via Es. java esercizio 6 3 7 2 12 4 deve restituire 6 / 3 = 2 7 / 2 = 3 12 / 4 = 3 Se un divisore è zero il programma deve dare come output ad es. 5 / 0 -> Infinite In caso una stringa in ingresso non corrisponda ad un intero il programma deve stampare un messaggio di errore e terminare Se il numero di parametri è dispari il programma deve terminare lanciando una OddParametersException (da creare estendendo un’opportuna eccezione) e segnalando l’errore con un messaggio Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 25 / 27 Le eccezioni Esercizio Esercizio Implementare (almeno) due metodi: un main ed un metodo che scorra i parametri e ne esegua la divisione Gestire la divisione per zero tramite eccezioni (non controllare prima dell’operazione che il divisore sia diverso da zero) La trasformazione da stringa ad intero può essere fatta con il metodo public int Integer.parseInt(String s) Questo lancia una NumberFormatException se la stringa argomento non rappresenta un intero In caso di interruzione del programma a fronte dei vari errori, implementare per alcuni un meccanismo dove l’eccezione viene propagata fino alla JVM e per altri un modo per intercettarla e dare un messaggio definito nel codice Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 26 / 27 Le eccezioni Esercizio Esercizio Alternativamente, nel caso di un parametro non intero stampare un messaggio di errore ma invece di terminare procedere ignorando il valore errato In questo caso lanciare una OddParametersException solo se il numero di parametri corretti è dispari Scrivere la seconda versione dell’esercizio riutilizzando più possibile il codice realizzato per la prima; fare cosı̀ in modo che le differenze tra i due codici siano minimali Stefano Brocchi Laboratorio di reti I 13 ottobre, 2009 27 / 27