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