Corso di Laurea in Ingegneria Informatica e delle Telecomunicazioni Corso di Telematica II A. A. 2010 - 2011 Programmazione client/server in Java Esercitazione 2 21 giugno 2011 Filippo Gramegna Telematica II A.A. 2009/10 Introduzione DEE - Politecnico di Bari • Da notare: – Gestione delle eccezioni • Blocco try • Blocchi catch (uno per ciascuna classe di eccezione, dalla più specifica alla più generica) • Blocco finally • E inoltre: – Ciclo do ... while – Lettura bufferizzata da file • L'uso degli stream in Java rende le operazioni di lettura (scrittura) uniformi indipendentemente dalla sorgente (destinazione): dispositivo, file, socket • Per leggere (scrivere) occorre creare un oggetto della sottoclasse di Reader (Writer) adatta Telematica II A.A. 2009/10 Gestione delle eccezioni DEE - Politecnico di Bari • Un'eccezione indica che si è verificato un evento non convenzionale durante l'esecuzione di un programma • Il sistema di gestione delle eccezioni in Java è basato sull'assunzione che il metodo che rileva l'evento generalmente non è in grado di gestirlo, piuttosto lancia (throw) un'eccezione • Di norma esiste un'altra porzione di codice che cattura (caught) l'eccezione e la gestisce Telematica II A.A. 2009/10 Blocco try-catch DEE - Politecnico di Bari • Il codice in grado di lanciare eccezioni viene racchiuso in un blocco try • Di norma esiste uno o più blocchi catch, che specificano il tipo di eccezione che possono gestire e contengono il codice per gestirla • Di norma esiste un blocco finally che contiene il codice da eseguire, indipendentemente dal verificarsi dell'eccezione Telematica II A.A. 2009/10 Lanciare un'eccezione DEE - Politecnico di Bari • Quando in un proprio metodo, si vuole lanciare un'eccezione, si usa la keyword throw, seguita da un oggetto di una classe derivata da Throwable • Quando viene lanciata un'eccezione, il controllo esce dal blocco try e passa alla prima clausola catch • I metodi che possono lanciare eccezioni, devono dichiararlo esplicitamente nella loro signature, usando la keyword throws, seguita dalla classe di eccezione che possono lanciare Telematica II A.A. 2009/10 Stream di I/O DEE - Politecnico di Bari • L'I/O in Java è basato sul concetto di stream (flusso), che rappresenta una connessione ad un canale di comunicazione • Uno stream è quindi collegato ad un dispositivo fisico di I/O • Esistono sia stream di input che di output Telematica II A.A. 2009/10 Proprietà degli stream DEE - Politecnico di Bari • sono FIFO: ciò che viene scritto da un OutputStream viene letto nello stesso ordine dal corrispondente InputStream • sono ad accesso sequenziale: non è fornito alcun supporto per l'accesso casuale • sono read-only oppure write-only: uno stream consente di leggere (InputStream) o scrivere (OutputStream) ma non entrambe le cose. Se ambedue le funzioni sono richieste, ci vogliono 2 stream distinti: questo è un caso tipico delle connessioni di rete: da una connessione (socket) si ottengono due stream, uno in scrittura e uno in lettura • sono bloccanti: la lettura blocca il programma che l'ha richiesta finchè i dati non sono disponibili. Analogamente, la scittura blocca il richiedente finchè non è completata • quasi tutti i loro metodi possono generare eccezioni Telematica II A.A. 2009/10 Esercizio 3 (1/3) DEE - Politecnico di Bari • Gestione delle eccezioni import java.io.*; ExceptionTest.java /** * Mostra la gestione delle eccezioni in Java. * * @author Floriano Scioscia */ public class ExceptionTest { /** * Metodo di avvio del programma * * @param args argomenti passati dalla riga di comando */ public static void main(String[] args) throws IllegalArgumentException, IOException { /* Se non viene passato come parametro il nome di un file, * lancia un'eccezione di numero di argomenti illegale */ if (args.length != 1) throw new IllegalArgumentException("Uso: java ExceptionTest <filename>"); Telematica II A.A. 2009/10 Esercizio 3 (2/3) DEE - Politecnico di Bari // Oggetto per leggere da file BufferedReader reader = null; try { // Crea un oggetto per lettura da file bufferizzata; // il costruttore di FileReader lancia // un'eccezione di classe FileNotFoundException se il // file non viene trovato reader = new BufferedReader(new FileReader(args[0])); // Legge il file una riga per volta e lo mostra a video String s = null; do { // Legge una riga del file; // puo' lanciare un'eccezione di classe IOException s = reader.readLine(); // Stampa a video la riga if (s != null) System.out.println(s); } while(s != null); Telematica II A.A. 2009/10 Esercizio 3 (3/3) DEE - Politecnico di Bari } catch(FileNotFoundException fnfe) { // file non trovato System.out.println("Il file " + args[0] + " non e' stato trovato."); fnfe.printStackTrace(); } catch(IOException ioe) { // errore di I/O System.out.println("Errore di lettura del file."); ioe.printStackTrace(); } finally { // Il contenuto del blocco finally e' eseguito in ogni caso // Chiude il file; puo' lanciare un'eccezione // di classe IOException (che sarebbe quindi opportuno // catturare) con un altro blocco try ... catch reader.close(); } } } Telematica II A.A. 2009/10 Esercizio 4 (1/4) DEE - Politecnico di Bari • Thread PrintThread.java /** * Semplice thread che stampa a video * un messaggio 10 volte * * @author Floriano Scioscia */ public class PrintThread extends Thread { /** * Costruttore * @param message messaggio da mostrare */ public PrintThread(String message) { /* Il costruttore di Thread piu' semplice e' * senza parametri. Quello usato qui riceve * come parametro una stringa, che funge * da nome del thread (utile per distinguere * i diversi thread di un'applicazione). */ super(message); } Telematica II A.A. 2009/10 Esercizio 4 (2/4) DEE - Politecnico di Bari } /** * Viene chiamato quando e' invocata * l'esecuzione del thread usando * il metodo <code>start()</code> * ereditato da Thread. */ public void run() { for (int i = 0; i < 10; i++) { // Stampa a video il numero e il nome del thread System.out.println(i + " " + getName()); try { /* Il metodo sleep() mette in stato dormiente * il thread per un certo tempo, in questo * caso un numero casuale generato con * Math.random(). Se ci sono altri thread * in stato attivo, la JVM ne selezionera' * uno e lo mettera' in run. */ sleep((long)(Math.random() * 1000)); } catch (InterruptedException e) { } } System.out.println("Fine " + getName()); } Telematica II A.A. 2009/10 Esercizio 4 (3/4) DEE - Politecnico di Bari ThreadTest.java /** * Crea e avvia 2 thread * * @author Floriano Scioscia */ public class ThreadTest { public static void main (String[] args) { PrintThread t1 = new PrintThread("Topolino"); PrintThread t2 = new PrintThread("Paperino"); t1.start(); t2.start(); } } Telematica II A.A. 2009/10 Esercizio 4 (4/4) DEE - Politecnico di Bari • Da notare: – Thread • • • • Costruttori Un thread svolge il suo lavoro nel metodo ereditato run() Avviare un thread con start() [ Arrestare un thread con stop() ] Telematica II A.A. 2009/10 Esercizio 5 (1/6) DEE - Politecnico di Bari • Strutture dati dinamiche • Da notare: – Strutture dati e algoritmi del Java Collections Framework (forniti dal package java.util) – Cfr. Java Tutorial per un approfondimento • E inoltre: – Strutture dati parametrizzate con tipi generici • I tipi generici (Java generics) sono stati introdotti nella versione 5 del linguaggio Java (corrispondente al JDK 1.5) • Cfr. Java Tutorial per un approfondimento Telematica II A.A. 2009/10 Esercizio 5 (2/6) DEE - Politecnico di Bari CollectionsExample.java import java.util.*; /** * Classe che mostra le funzionalita' di base del Java Collections * Framework (JCF). Esso fornisce una gerarchia di interfacce per * le strutture dati dinamiche fondamentali (Set, List, Queue e Map). * Ciascuna interfaccia ha diverse implementazioni, che consentono * tutte le medesime operazioni ma con prestazioni diverse: la scelta * andra' effettuata in base alle esigenze della applicazione. * Sono inoltre forniti metodi che implementano efficientemente * alcuni algoritmi di uso frequente (ricerca, ordinamento, etc.). * @author Floriano Scioscia */ public class CollectionsExample { /** * Metodo di avvio del programma * @param args argomenti passati dalla linea di comando */ public static void main(String[] args) { Telematica II A.A. 2009/10 Esercizio 5 (3/6) DEE - Politecnico di Bari /* Lista dinamica di oggetti di classe String, * per contenere le stringhe ricevute dalla riga di comando * List e' l'interfaccia del JCF per una lista ordinata. * ArrayList e' una delle classi che implementano List. * E' molto usata perche' generale ed efficiente. */ */ List<String> argList = new ArrayList<String>(); for (int i=0; i<args.length; i++) { // Aggiunge un elemento in coda alla lista argList.add(args[i]); } // Stampa a video la lista System.out.println("Lista: " + argList); /* Gli iteratori consentono di scorrere strutture * dati sequenziali un elemento alla volta */ Iterator<String> it = argList.listIterator(); // Ottiene un iteratore while (it.hasNext()) { // Vero se la lista non e' finita // Il metodo next() passa all'elemento successivo della lista System.out.println(it.next()); } Telematica II A.A. 2009/10 Esercizio 5 (4/6) DEE - Politecnico di Bari /* La classe java.util.Collections contiene metodi statici * che implementano algoritmi di utilita' generale. */ Collections.sort(argList); // ordina System.out.println("Lista ordinata: " + argList); Collections.reverse(argList); // inverte l'ordine degli elementi System.out.println("Lista invertita: " + argList); Collections.shuffle(argList); // elementi in ordine pseudocasuale System.out.println("Lista mescolata: " + argList); // Gli elementi della lista hanno un indice che parte da zero String second = argList.get(1); // ottiene il secondo elemento argList.set(1, "secondo"); // sostituisce il secondo elemento System.out.println("Lista dopo sostituzione: " + argList); // Due possibilita' per rimuovere un elemento argList.remove(1); // rimuove l'elemento alla posizione specificata System.out.println("Rimosso il secondo elemento: " + argList); argList.remove("via"); // rimuove (se presente) l'oggetto passato come parametro System.out.println("Rimosso l'elemento 'via': " + argList); Telematica II A.A. 2009/10 Esercizio 5 (5/6) DEE - Politecnico di Bari /* L'interfaccia Map rappresenta invece un dizionario, cioe' * una sequenza di coppie chiave-valore. L'implementazione * piu' usata e' data dalla classe HashMap. * Usiamola per contare le ricorrenze di ciascun parametro. * Notare anche qui che le strutture dati sono generiche, * vanno parametrizzate in base alla classe di oggetti che * dovranno contenere, in modo che il compilatore possa * controllare la correttezza delle assegnazioni. */ Map<String,Integer> argCount = new HashMap<String,Integer>(); it = argList.listIterator(); while (it.hasNext()) { String s = it.next(); /* Il metodo get restituisce il valore corrispondente * alla chiave passata come parametro, oppure null * se a tale chiave non corrisponde nessun valore */ Integer n = argCount.get(s); Telematica II A.A. 2009/10 Esercizio 5 (6/6) DEE - Politecnico di Bari if (n == null) { // put inserisce una coppia chiave-valore argCount.put(s, new Integer(1)); } else { /* Se (come in questo caso) la chiave e' gia' * presente nel dizionario, put sostituisce * il valore ad essa corrispondente */ Integer n2 = new Integer(n.intValue() + 1); argCount.put(s, n2); } } } } // Stampa il dizionario System.out.println("Conta degli argomenti: " + argCount); // fine main