4 StringTokenizer: esempio import java.io.*; import java.util.*; Lettura di matrici da file class prova { public static void main(String[] a) { String s="ciao a tutti"; StringTokenizer st=new StringTokenizer(s); while(st.hasMoreTokens()) { System.out.println(st.nextToken()); } } } 2 5 Come procedere? Lettura matrice: esempio - I import java.io.*; import java.util.*; Occorre leggere una riga per volta Suddividere la riga in token (sottostringhe) separate da delimitatori) e aggiungere le sottostringhe alla matrice. class p2 { public static void main(String[] a) throws Exception { int[][] mat=new int[2][3]; String filename="prova.txt"; BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(new File(filename)))); String line =br.readLine(); int x=0; int y; 3 La classe StringTokenizer Consente di suddividere una stringa in Tokens, separati da un delimitatore Utilizzo simile all’ Enumeration Parte del package java.util Costruttori: – StringTokenizer(String str) crea uno StringTokenizer, utilizzando il carattere spazio “ “ come separatore – StringTokenizer(String str, String delim): crea uno StringTokenizer, utilizzando la stringa delim come separatore Metodi di accesso ai tokens: – boolean hasMoreTokens() controlla se ci sono ancora token da leggere – String nextToken() restituisce il token successivo 6 Lettura matrice: esempio - II while(line !=null) { y=0; StringTokenizer st=new StringTokenizer(line,";"); while(st.hasMoreTokens()) { mat[x][y]=Integer.parseInt(st.nextToken()); y++; } x++; line=br.readLine(); } 7 Lettura matrice: esempio - III 10 Rispondere all’imprevisto for(x=0;x<2;x++) { for(y=0;y<3;y++) System.out.print(mat[x][y]+" "); System.out.println(); } Consideriamo il caso in cui l’argomento del metodo parseInt è “pippo” Il metodo parseInt non può correggere l’errore Non può far sapere all’utente che c’è stato un errore } } – Il metodo restituisce un int … Questo non è compito di parseInt 11 Exception Un modo alternativo di terminazione dei metodi basato sull’uso dell’istruzione throw Eccezioni throw riferimento – dove riferimento è un oggetto di una sottoclasse della classe Exception, solitamente: throw new Exception-Class(Argomento String) – dove Exception-Class è una sottoclasse di Exception Quando il metodo esegue l’istruzione throw, si dice che lancia (throw) un’eccezione. 9 Previsione dell’imprevisto Immaginiamo il seguente codice int numberInStock = Integer.parseInt(br.readLine()); Cosa succede se: – L’oggetto BufferedReader rappresenta un file su floppy disk che l’utente ha erroneamente estratto ? – L’oggetto BufferedReader rappresenta una connessione alla rete che è fallita a causa di un guasto ? – L’operatore immette una sequenza di cifre troppo lunga ? – L’operatore non immette una sequenza di cifre ? 12 Lanciare un’eccezione Consideriamo la catena di chiamate main Æ method1 Æ method2 – Supponiamo che method2 incontra un imprevisto e lancia l’eccezione throw riferimento ad oggetto Exception – Il metodo in esecuzione termina immediatamente, l’Exception passa attraverso ogni invocazione della catena, forzando ogni metodo a terminare. Viene visualizzato: Some Exception at TryThrow.method2(TryThrow.java:18) at TryThrow.method1(TryThrow.java:15) at TryThrow.main(TryThrow.java:12) 13 Esempio 16 Etichettatura delle eccezioni Il costruttore di una Exception prende come argomento una String che viene stampata quando si visualizza la catena delle invocazioni Il metodo parseInt contiene un’istruzione simile a throw new NumberFormatException(Argomento String) Questa istruzione crea un nuovo ogetto NumberFormatException e lancia il riferimento a questo oggetto. NumberFormatException è una sottoclasse di Exception throw new FileNotFoundException(“log file is” + “always necessary”); 14 La clausola throws 17 Trattare l’imprevisto Come evitare la terminazione di un programma in caso di eccezione ? Il verbo throw non è del tutto sconosciuto … – Spesso Java richiede che si includa la clausola throws nell’intestazione della dichiarazione di un metodo: – Java fornisce ai metodi un modo per catturare (catch) qualsiasi Exception lanciata sul loro percorso dai metodi che invocano – Catturando l’Exception si interrompe la catena che porta alla terminazione del programma – viene recuperato il controllo e si può trattare la situazione in modo meno drastico public static void main(String[] a) throws Exception – Qualsiasi metodo che potrebbe lanciare un’Exception deve indicarlo nella sua dichiarazione con la clausola throws – La clausola throws è composta dalla parola chiave e dalla lista delle sottoclassi di Exception che possono essere lanciate dal metodo – Questo requisito si applica anche ai metodi che possono lanciare l’Exception indirettamente invocando altri metodi Per catturare una Exception, le istruzioni contenenti invocazioni di metodi che lanciano Exception devono essere tra parentesi e precedute dalla parola chiave try 15 La classe Exception Il riferimento che appare nell’istruzione throw deve riferirsi a un oggetto della classe Exception – Ogni oggetto istanza di una sottoclasse di Exception è anche un oggetto Exception Perché esistono più classi Exception ? – distinzioni tra i vari tipi di situazioni impreviste, es: throws IOException throws FileNotFoundException, RemoteException: – IOException è una sottoclasse di Exception – FileNotFoundException e RemoteException sono sottoclassi di IOException 18 Try try { // parte try someObject.someMethod(); } catch (Exception e) { // parte catch le istruzioni sono eseguite solo se l’eccezione è lanciata all’interno di try } 19 static Movie readMovie(BufferedReader br) throws IOException { String name; int playingTime; boolean gotGoodData; // True if name and playingTime have valid data Movie newMovie; name = br.readLine(); gotGoodData = false; while (!(name==null || gotGoodData)) { gotGoodData = true; // Optimistic! try { playingTime = Integer.parseInt(br.readLine()); } catch (NumberFormatException e) { // Skip this movie; do next one. System.err.print("Bad playing time data for "+name); System.err.println(" -- movie skipped"); gotGoodData = false; name = br.readLine(); } } if (name==null) return null; else return new Movie(name,playingTime); } 22 Versione corretta Esempio static Movie readMovie(BufferedReader br) throws IOException { String name; int playingTime; Movie newMovie; name = br.readLine(); if(name == null) return null; playingTime = Integer.parseInt(br.readline()); newMovie = new Movie(name, playingTime); return newMovie; } Come gestire un errore dei dati in ingresso inviando un messaggio all’utente ? 20 Esempio rivisto static Movie readMovie(BufferedReader br) throws IOException { String name; int playingTime; Movie newMovie; name = br.readLine(); if(name == null) return null; try { playingTime = Integer.parseInt(br.readLine()); } catch (NumberFormatException e) { // Skip this movie; do next one System.err.print("Bad playing time data for "+name); throw e; } newMovie = new Movie(name, playingTime); return newMovie; } 21 static Movie readMovie(BufferedReader br) throws IOException { String name; int playingTime; Movie newMovie; name = br.readLine(); if(name == null) return null; try { playingTime = Integer.parseInt(br.readLine()); } catch (NumberFormatException e) { // Skip this movie; do next one System.err.print("Bad playing time data for "+name); System.err.println(" -- movie skipped"); name = br.readLine(); if(name == null) return null; playingTime = Integer.parseInt(br.readLine()); newMovie = new Movie(name, playingTime); return newMovie; } // questo codice è eseguito se parseInt non lancia una NumberFormatException newMovie = new Movie(name, playingTime); return newMovie; } // dove è il problema ? Rimediare ad un errore 23 Responsabilità per l’imprevisto Ogni oggetto si assume la responsabilità del suo comportamento (comprese le circostanze impreviste) – Ad esempio consideriamo gli oggettI: • NetHeadlineScanner modella un servizio di titoli in rete. Il suo compito è visualizzare i titoli che contengono alcune parole chiave. I titoli sono ottenuti dall’oggetto NetHeadlines • NetHeadlines ottiene in continuazione i titoli delle notizie da una qualsiasi delle varie sorgenti alternative ed è implementato usando il NetReader • L’oggetto NetReader legge in continuazione le ultime informazioni da una sorgente della rete. A sua volta, il NetReader può essere implementato usando il BufferedReader • L’oggetto BufferedReader è costruito dall’InputStream consegnato dall’oggetto Socket connesso. Socket è la classe predefinita di java che modella le connessioni di basso livello alla rete 24 Responsabilità per l’imprevisto (2) L’oggetto NetHeadlineScanner invoca il metodo readLine della classe NetHeadlines che a sua volta invoca il metodo readLine della classe NetReader, che a sua volta invoca il metodo readLine della classe BufferedReader In questo caso l’imprevisto è la non disponibilità improvvisa della sorgente corrente di notizie – Quali classi dovrebbero assumersi la responsabilità dell’inconveniente ? – Quale comportamento dovrebbero seguire ? 25 Responsabilità per l’imprevisto (3) Si può risalire al punto in cui è stata generata l’Exception ed esaminare gli oggetti sulla catena di invocazioni cercando di individuare quale oggetto sia in grado di agire rispetto all’eccezione 28 CheckURL: prima versione import java.net.*; import java.io.*; class CheckURL { public static void main(String[] a) throws Exception { URL u = new URL(a[0]); HttpURLConnection uc = (HttpURLConnection) u.openConnection(); int responseCode = uc.getResponseCode(); System.out.println(responseCode); if (responseCode >= 300) System.out.println("bad"); else System.out.println("good"); } Nel caso in cui non è possibile stabilire una connessione perché il server web non esiste il programma dovrebbe rispondere bad, ma … – BufferedReader.readLine lancia l’Exception • Non sarà lui a catturarla • Non è riuscito a trattare la non disponibilità della sorgente di rete perché il BufferedReader è una sorgente di dati idealizzata e non sa se i dati che sta fornendo provengano dalla rete, da un file o dalla tastiera • Per questo lancia un’Exception 26 Responsabilità per l’imprevisto (4) Come si comportano gli altri oggetti ? – L’oggetto NetReader sa che sta leggendo dalla locazione di rete della sua sorgente • Ottenere i dati è il suo comportamento • Se i dati non sono disponibili, lancia un’eccezione – L’ogetto NetHeadlines conosce delle sorgenti di rete alternative • Potrebbe rispondere catturando l’Exception, selezionando un indirizzo di rete diverso creando un oggetto NetReader basato sulla nuova sorgente di rete e continuando – NetHeadlineScanner non deve fare niente … • Potrebbe trattare l’Exception meglio di NetHeadlines, ma questo non rientra nelle sue responsabilità (che riguardano solo la selezione dei titoli) 27 Le eccezioni non sono sempre errori Scriviamo un programma che riceve un URL come argomento dalla linea di comando e stampa “good” se la URL corrisponde all’indirizzo di una pagina web, “bad” altrimenti – Si possono usare i response codes restituiti dai web server – I codici maggiori o uguali a 300 indicano un errore nella URL • Ad esempio 404 significa che la pagina non esiste • 403 significa che la risorsa non è accessibile – La classe HttpURLConnection nella libreria java.net modella le connessioni HTTP a risorse web specificate da URL – Possiamo creare tale oggetto mandando un messaggio openConnection ad un oggetto URL – Avuto un oggetto HttpURLConnection, gli possiamo mandare un messaggio getResponseCode 29 CheckURL: versione corretta import java.net.*; import java.io.*; class CheckURL { public static void main(String[] a) throws Exception { try { URL u = new URL(a[0]); HttpURLConnection uC = (HttpURLConnection) u.openConnection(); int responseCode = uc.getResponseCode(); System.out.println(responseCode); if (responseCode >= 300) System.out.println("bad"); else System.out.println("good"); } catch (Exception e) { System.out.println("bad"); } } }