Programmazione in Java Quarta lezione Cristian Del Fabbro Di cosa si parla oggi? ● Eclipse ● Garbage Collector ● I/O da tastiera e da file ● Eccezioni ● Alcune classi utili ● Una classe per i numeri complessi ● Esempio per casa Eclipse ● ● ● IDE (Integrated Development Environment) – scrivere – compilare – eseguire È scritto principalmente in Java e pensato per sviluppare programmi in Java Disponibili svariati plugin (scritti in Java) – VisualJava Perché Eclipse? ● Autocompletamento ● Help in linea durante la digitazione ● ● ● ● Segnala gli errori di sintassi mentre si scrive il codice Suggerisce cosa fare per correggere gli errori più comuni Mostra la gerarchia dei pacchetti e delle classi Permette il debug Garbage Collector ● ● ● Quando un oggetto non ha riferimenti che puntano ad esso il programma non lo può più usare (garbage) Generalmente bisogna ricordarsi di liberare la memoria allocata e non più utilizzata Java gestisce in automatico la deallocazione della memoria non più utilizzata – il programmatore ha un problema in meno I/O da tastiera ● Serve per poter interagire con l'utente ● L'INPUT permette di ricevere dei dati – ● System.in è un InputStream L'OUTPUT permette di visualizzare dei dati – System.out è un OutputStream EasyIn ● ● È una semplice classe che permette di ricevere l'input da tastiera senza curarsi dei dettagli Permette di leggere: – numeri interi – readInt() – readLong() – numeri reali – readFloat – readDouble() – stringhe – readString() – readChar() – valori booleani – readBoolean() Salutare l'utente public class Hello { public static void main(String[] args){ EasyIn input = new EasyIn(); System.out.println("Ciao, come ti chiami?"); String nome = input.readString(); System.out.println("Ciao " + nome + "!"); } } I/O da file ● I dati vengono presi e scritti su un file ● Si parla di flusso (stream) di dati ● ● Attraverso l'INPUT si prelevano i dati da un file Attraverso l'OUTPUT si scrivono i dati in un file Leggere un file ● Quando si vuole prelevare i dati da un file bisogna: – sapere il percorso del file – aprire uno stream di input – prelevare i dati – controllare se si è raggiunta la fine del file (EOF) – verificare se ci sono degli errori – chiudere il file Classi per leggere ● ● ● Ad un file bisogna associare uno stream di input: – FileInputStream – FileReader Possono leggere solo array di caratteri Una classe più utile è BufferedReader che permette di leggere una riga intera e memorizzarla in una stringa Leggere un file di testo String name = “nomefile”; FileReader f = new FileReader(name); BufferedReader file = new BufferedReader(f); while (file.ready()) { String line = file.readLine(); System.out.println(line); } file.close(); Scrivere su un file ● Quando si vuole scrivere dei dati su un file bisogna: – sapere il percorso del file – aprire uno stream di output – scrivere i dati – verificare se ci sono degli errori – chiudere il file Classi per scrivere ● ● ● Ad un file bisogna associare uno stream di output: – FileOutputStream – FileWriter Possono scrivere solo array di caratteri Una classe più utile è PrinterWriter che permette di usare i metodi print e println come con lo standard output Numerare le righe di un file FileReader r = new FileReader(inName); BufferedReader fileInput = new BufferedReader(r); FileWriter w = new FileWriter(outName); PrinterWriter fileOutput = new PrinterWriter(w); int count = 1; while (fileInput.ready()) { String line = fileInput.readLine(); fileOutput.println(count + ") " + line); count++; } fileInput.close(); fileOutput.close(); // Ricordarsi di chiudere SEMPRE i file in scrittura! Accesso casuale ai file (1) ● ● I file trattati come stream possono essere letti in una sola direzione: una volta letto un byte si passa al successivo e non si può tornare indietro Per poter andare “avanti” e “indietro” in un file bisogna usare la class RandomAccessFile che permette di spostarsi avanti e indietro all'interno del file Accesso casuale ai file (2) ● ● Un file ad accesso casuale si può aprire in lettura, in scrittura o in entrambi i metodi: – new RandomAccessFile(“file.txt”,”r”) – new RandomAccessFile(“file.txt”,”w”) – new RandomAccessFile(“file.txt”,”rw”) oltre ai metodi normalmente disponibili per leggere e scrivere sono presenti: – void seek(long i) // serve per posizionarsi al byte i-esimo del file – long getFilePointer() // ritorna la posizione del prossimo byte da leggere Eccezioni (1) ● ● ● Quando si lavora con dei file (o in generale quando si interagisce con il “mondo” esterno ad un programma) si possono generare delle eccezioni ed errori. Una eccezzione è un oggetto che definisce una situazione inusuale o erronea. Un errore è simile ad una eccezione ma in generale non può essere corretta e non può essere intercettato Eccezioni (2) ● ● ● I metodi delle classi possono generare eccezioni Quando si utilizza un metodo che può generare un'eccezione bisogna “catturarla” Per far questo bisogna utilizzare la struttura “try/catch”: try { // chiamate a metodi che generano eccezioni } catch (ExceptionType exception) { // gestione dell'errore } Eccezioni: esempio import java.io.*; public class SimpleRead { public static void main (String[] args) { String name = “nomefile”; try { FileReader f = new FileReader(name); // genera eccezione “FileNotFound” BufferedReader file = new BufferedReader(f); while (file.ready()) { String line = file.readLine(); // genera eccezione di “I/O” System.out.println(line); } file.close(); } catch (FileNotFoundException e) { System.out.println("Il file non è stato trovato!"); } catch (IOException e) { System.out.println("Errore nella lettura del file."); } } } Eccezioni: metodo alternativo ● ● ● Esiste un altro modo di trattare le eccezioni ed è quello di non gestirle ma ti notificarle al metodo chiamante Si demanda la gestione ad un livello superiore Per far questo bisogna usare la sintassi: – public void read throws ExceptionType [, ExceptionType ] { // corpo del metodo } Esempio Throws (1) public class SimpleReadThrows { BufferedReader file; public SimpleReadThrows(String name) throws FileNotFoundException { FileReader f = new FileReader(name); file = new BufferedReader(f); } public void read() throws IOException { while (file.ready()) { String line = file.readLine(); System.out.println(line); } file.close(); } // continua nella prossima slide Esempio Throws (2) // continua dalla precedente slide public static void main(String[] args) throws IOException { EasyIn input = new EasyIn(); System.out.println("Quale file vuoi visualizzare?"); String name = input.readString(); try { SimpleReadThrows srt = new SimpleReadThrows(name); srt.read(); } catch (FileNotFoundException e) { System.out.println("File non trovato!"); } } } Package ● Per poter usare classi già pronte ci sono tre modi: – invocare esplicitamente la classe: java.util.Vector vector = new java.util.Vector(); – importare la classe: import java.util.Vector; // all'inizio del file [...] Vector vector = new Vector(); – importare tutto il pacchetto: import java.util.*; // all'inizio del file [...] Vector vector = new Vector(); StringTokenizer = new StringTokenizer(); Vector ● ● java.util.Vector – permette di gestire array che cambiano dimensione e tipo in modo dinamico – funziona solo per le classi, non per tipi primitivi metodi: – void addElement(Object obj) – void insertElementAt(Object obj, int index) – removeElementAt(int index) – Object elementAt(int index) – boolean size() Esempio di uso di Vector Vector vector = new Vector(); vector.addElement(“Primo elemento”); vector.addElement(“Ultimo elemento”); vector.insertElementAt(“Secondo elemento”,1); vector.insertElementAt(“Terzo elemento”,1); vector.removeElementAt(1); vector.insertElementAt(“Terzo elemento”,2); for (int i=0; i < vector.size(); i++) { System.out.println((String)vector.elementAt(i)); } StringTokenizer ● java.util.StringTokenizer – serve per processare una stringa composta da più campi. Es.: Mario|Rossi|impiegato|Udine ● costruttore: StringTokenizer(String str) ● metodi: – int countTokens() – boolean hasMoreTokens() – String nextToken() Esempio di StringTokenizer StringTokenizer st = new StringTokenizer("Questa è una prova"); int n = st.countTokens(); for (int i=0; i < n ; i++) System.out.println(st.nextToken()); st = new StringTokenizer("Mario|Rossi|impiegato|Udine","|"); while (st.hasMoreElements()) System.out.println(st.nextToken()); Date ● ● ● java.util.Date – sapere data e ora in cui viene eseguito lo script – semplici operazioni di confronto fra date costruttori: – Date() – Date(long date) metodi: – boolen after(Date arg) boolean equals(Date arg) boolean before(Date arg) GregorianCalendar ● java.util.GregorianCalendar – ● serve per “formattare” le date a seconda del calendario locale della località costruttori: – GregorianCalendar() – GregorianCalendar(int year, int month, int day) – GregorianCalendar(int year, int month, int day, int hour, int min) – GregorianCalendar(int year, int month, int day, int hour, int min, int sec) Esempio di uso di Date Date date = new GregorianCalendar(year,month,day).getTime(); GregorianCalendar now_gregorian = new GregorianCalendar(); int day_now = now_gregorian.get(Calendar.DATE); int month_now = now_gregorian.get(Calendar.MONTH); int year_now = now_gregorian.get(Calendar.YEAR); Date now = new GregorianCalendar(year_now,month_now,day_now).getTime(); DateFormat df = DateFormat.getDateInstance(DateFormat.LONG); System.out.println("Data attuale: " + df.format(now)); System.out.println("Data inserita: " + df.format(date)); if (date.equals(now)) { System.out.println("Le due date sono identiche"); } else if (date.before(now)) { System.out.println("La data inserita è precedente alla data attuale"); } else { // implicitamente vale date.after(now) System.out.println("La data inserita è seguente alla data attuale"); } Alcuni esempi di classi ● ● ● ● Le classi sono costituite da uno o più costruttori, dalle proprietà e dai metodi i costruttori servono per inizializzare l'oggetto le variabili servono per caratterizzare un oggetto i metodi servono per l'interazione fra gli oggetti Il numero complesso (1) ● ● ● Un numero complesso è caratterizzato da una parte reale e una parte immaginaria [proprietà => variabili] Bisogna costruire un oggetto “numero complesso” a partire dalla parte reale e immaginaria [costruttore] Dell'oggetto bisogna sapere la sua parte reale e immaginaria, poter stamparlo in formato “n+mi” e poter fare alcune operazioni (come la somma) [metodi] Il numero complesso (2) ● Le proprietà (variabili) del numero complesso sono: – float real; – float imm; Il numero complesso (3) ● Costruttori: – se non ci sono dati crea il numero 0+0i Complex() { real = 0; imm = 0; } – dati i numeri “n” e “m” crea il numero n+mi Complex(float n, float m) { real = n; imm = m; } Il numero complesso (3) ● ● ritorna la parte reale e immaginaria di un numero: – public float getReal() { return real; } – public float getImm() { return imm; } modulo del numero complesso – public float getModule() { return (float)Math.sqrt(real*real + imm*imm); } ● somma di un numero complesso – ● public void addComplex(Complex value) { real += value.getReal(); imm += value.getImm(); } ritornare il complesso coniugato – public Complex getConiugate() { return new Complex(real,-imm); } Il numero complesso (4) ● Restituire un formato “stringa” del numero complesso per poterlo stampare a video – public String toString() { String s = new String(); s += (new Float(real)).toString(); if (imm >=0) s += “+”; s += (new Float(imm)).toString() ; s += “i”; return s; } Il numero complesso (5) ● Esempio di utilizzo: Complex a = new Complex(); // 0+0i Complex b = new Complex(5,3); // 5+3i Complex c = new Complex(-6,4); // -6+4i a.addComplex(b); // somma 5+3i ad a a.addComplex(c.getConiugate()); // somma -6-4i ad a System.out.println("a vale: " + a.toString()); // a vale: -1.0-1.0i System.out.println("La parte reale di a e': " + a.getReal()); // La parte reale di a e': -1.0 System.out.println("La parte immaginaria di a e': " + a.getImm()); // La parte immaginaria di a e': -1.0 System.out.println("Il modulo di a e': " + a.getModule()); // Il modulo di a e': 1.4142135 Esempio per casa (1) ● ● Scrivere una classe per memorizzare i dati di una persona: – nome – cognome – luogo di nascita – data di nascita Aggiungere alla classe dei metodi che ritornino il nome e il cognome, la data di nascita in formato esteso e l'età Esempio per casa (2) ● Preparare un file con una serie di informazioni per riga, ad es: – ● Mario|Rossi|impiegato|Udine|23/3/1952 Carlo|Bianchi|studente|S. Donà|2/12/1990 Franco|Franchi|comico|Frafroreano|4/4/1944 Scrivere un programma che legge il file e scrive un altro file come nell'esempio della prossima slide Esempio per casa (3) Mario Rossi di professione impiegato Nato a Udine il 23 febbraio 1952 Quest'anno ha già compiuto 57 anni Carlo Bianchi di professione studente Nato a S. Donà il 12 dicembre 1990 Quest'anno deve compiere 15 anni Franco Franchi di professione comico Nato a Fraforeano il 4 aprile 1944 Quest'anno ha già compiuto 61 anni