Elementi di JAVA Tommaso Di Noia [email protected] Distribuzioni (java.com) ● ● ● JSE (Java Standard Edition): – Mette a disposizione un compilatore, vari tool per la gestione del codice, un appletviewer ed un ricco set di API per lo sviluppo di applicazioni e applet. JEE (Java Enterprise Edition): – Orientata allo sviluppo di applicazioni distribuite. Mette a disposizione un insieme di semplici tool per la gestione di un application server ed un semplice DBMS (cloudscape) ed un ricco set di API per lo sviluppo di servlet e di tutte le tecnologie che ruotano attorno ad esse. JME (Java Micro Edition): – Un ambiente altamente ottimizzato per i dispositivi con scarsa disponibilità di risorse hardware (smart card, telefonini, palmari). Mette a disposizione un ricco set di API per lo sviluppo di midlet ed alcuni tool di gestione (tra i quali vari simulatori di dispositivi di telefonini). Java Stack Documentazione su java Ambienti di sviluppo integrato (IDE): ● ● ● NetBeans IDE Eclipse IntelliJ IDEA Documentazione su tutte le librerie presenti nelle distribuzioni: ● Java Doc – documentazione in formato ipertestuale http://docs.oracle.com/javase/7/docs/api/ Java - Caratteristiche ● Portabile: non prevede aspetti dipendenti dalla implementazione es. le dimensioni dei tipi predefiniti sono fisse ● ● ● ● Indipendente dall’architettura: il compilatore genera un bytecode interpretabile in processori diversi (Java è sia compilato che interpretato) Robusto: il compilatore riscontra molti errori che in altri linguaggi sono riscontrabili solo in esecuzione Sicuro: è destinato all’uso in ambienti distribuiti e di rete Altamente versatile: grazie ad un ricco set di API è possibile scrivere qualsiasi tipo di applicazione. Il bytecode file HW.java public class HW { public HW() { } public static void main(String[] args) { file HW.class compilatore javac codice sorgente System.out.println(“ Hello, WORLD!"); } bytecode 0 0:getstatic #2 <Field PrintStream System.out> 1 3:ldc1 #3 <String "Io ne ho viste di cose che voi umani\n non potreste nemmeno immaginarvi."> 2 5:invokevirtual #4 <Method void PrintStream.println(String)> 3 8:return } Hello, WORLD! interprete java Java Virtual Machine In the Java programming language, all source code is first written in plain text files ending with the .java extension. Those source files are then compiled into .class files by the javac compiler. A .class file contains bytecodes — the machine language of the Java Virtual Machine (JVM). The java launcher tool then runs your application with an instance of the Java Virtual Machine. http://docs.oracle.com/javase/tutorial/getStarted/intro/definition.html Portabilità Because the JVM is available on many different operating systems, the same .class files are capable of running on Linux OS, Microsoft Windows, Solaris OS or Mac OS. http://docs.oracle.com/javase/tutorial/getStarted/intro/definition.html Object-Oriented Programming ● What Is an Object? Software objects are conceptually similar to real-world objects: they too consist of state and relative behavior. An object stores its state in fields (variables in some programming languages) and exposes its behavior through methods (functions in some programming languages). ● What Is a Class? In the real world, you'll often find many individual objects all of the same kind. The structure and behavior of an object are defined by a class, which is a definition, or blueprint, of all objects of a specific type. An object must be explicitly created based on a class and an object thus created is considered to be an instance of that class. OOP's benefits ● ● ● ● Modularity: The source code for an object can be written and maintained independently of the source code for other objects. Once created, an object can be easily passed around inside the system. Information-hiding: By interacting only with an object's methods, the details of its internal implementation remain hidden from the outside world. Code re-use: If an object already exists, you can use that object in your program. Pluggability and debugging ease: If a particular object turns out to be problematic, you can simply remove it from your application and plug in a different object as its replacement. Classi e Oggetti in java ● Classe è l’unità fondamentale dei programmi java – – ● ● ● definisce la struttura degli oggetti contiene campi e metodi Creazione di un oggetto creazione di un’istanza della classe Per ogni classe è possibile istanziare un numero indefinito di oggetti Sintassi per la creazione di un oggetto ● NomeClasse oggetto = new CostruttoreClasse(); Metodo costruttore Esempio: Persona.java public class Persona { String nome; String cognome; public Persona(String nome, String cognome) { this.nome = nome; this.cognome = cognome; } public String getNomeCognome() { return this.nome + this.cognome; } } Esempio: istanza di Persona Persona pippo = new Persona(“Pippo”, “Super”); String nomeCognome = pippo.getNomeCognome(); // nomeCognome adesso è “Pippo Super” Metodi in java ● Sintassi per definire un metodo – ● Sintassi per chiamare un metodo: – ● ModificatoreAccesso tipo_restituito nome_metodo (Lista argomenti) { // dichiarazioni e statement} oggetto.metodo(argomenti) Metodi costruttori – – – – usati per inizializzare gli oggetti di una classe new costruttore permette di creare un nuovo oggetto nella classe hanno lo stesso nome della classe se il codice della classe non specifica alcun costruttore java fornisce costruttori predefiniti - senza argomenti che inizializzano i valori a quelli predefinti Esempio (1) : Prima.java public class Prima { private String modificata; private String originale; public Prima(String org) { originale = org; modificata = originale+"QUESTA E' LA STRINGA modificata"; System.out.println("E' stato creato un nuovo oggetto appartenente alla classe Useless \n"); } public void showModificata(){ System.out.println(modificata); } public void showOriginale(){ System.out.println(originale); } } Esempio (2) : UsaPrima.java public class UsaPrima { public UsaPrima() { } public static void main(String[] args) { Prima oggetto1 = new Prima("primo oggetto inutile creato \n"); oggetto1.showOriginale(); Prima oggetto2 = new Prima("secondo oggetto inutile creato \n"); oggetto2.showModificata(); } } Esempio (3) : UsaPrima java UsaPrima UsaPrima oggetto1 = new UsaPrima("primo oggetto inutile creato\n"); oggetto1.showOriginale(); oggetto1: Prima originale = “primo oggetto inutile creato \n” E' stato creato un nuovo oggetto appartenente alla classe Prima primo oggetto inutile creato Prima oggetto2 = new Prima("secondo oggetto inutile creato \n"); oggetto2.showModificata(); oggetto2: Prima originale = “secondo oggetto inutile creato \n” E' stato creato un nuovo oggetto appartenente alla classe Prima secondo oggetto inutile creato QUESTA E' LA STRINGA modificata Metodi in java ● Sintassi per definire un metodo modificatore_accesso tipo_restituito nome_metodo (Lista argomenti) { codice del metodo } Modificatori: private, public, e altri Tipi: void, int, float, String, e altri ● Sintassi per chiamare un metodo: – oggetto.metodo(argomenti) Metodi costruttori in java ● Sintassi per definire un costruttore modificatore_accesso nome_CLASSE (Lista argomenti) { codice del costruttore } Va definito con lo stesso nome della classe Il valore di ritorno è l'indirizzo dell'oggetto che è stato appena creato Il costruttore si usa solitamente per inizializzare le componenti degli oggetti Esempio: Persona.java public class Persona { String nome; String cognome; public Persona() { } public Persona(String nome, String cognome) { this.nome = nome; this.cognome = cognome; } . . } Esempio: Persona.java public class Persona { String nome; String cognome; Costruttore vuoto public Persona() { } public Persona(String nome, String cognome) { this.nome = nome; this.cognome = cognome; } . . } Costruttore con corpo Gli Oggetti in Java (ed altri particolari) (1) ● ● A differenza di altri linguaggi di programmazione orientati agli oggetti (es: C++, SmallTalk, Object Pascal) in Java l’allocazione degli oggetti è sempre dinamica, tutto viene caricato nella memoria heap. Non esiste un metodo distruttore. Il garbage collector della JVM si occupa di distruggere gli oggetti che non sono più referenziati. (La chiamata al garbage collector può essere forzata dall’utente) Gli Oggetti in Java (ed altri particolari) (2) ● Poiché non sono disponibili i puntatori (croce e delizia di ogni programmatore) per creare le strutture dati dinamiche (alberi, liste, code,…) sono messe a disposizione delle classi container che si occupano di gestire tali strutture (List, Map, Set). – Per gestire tali strutture esistono le classi iterator che permettono di separare la struttura dai metodi per accedervi. I tipi e i Wrapper ● int Integer ● byte Byte ● short Short ● long Long ● double Double ● float Float ● char Char ● boolean Boolean I tipi e i Wrapper EsempioWrapper.java Java PACKAGE ● È possibile raggruppare gruppi di classi in raccolte per organizzare il codice. – ● ● Può essere visto come l’equivalente di una libreria negli altri linguaggi di programmazione (C, Pascal, …) Il nome del package rispetta la struttura del file system (directory e subdirectory) I package possono essere raggruppati in file compressi (.zip, .jar). Tali file devono rispettare al loro interno la gerarchia delle directory. Java PACKAGE. Ex. PACKAGE: java.awt Classi apparteneti a java.awt PACKAGE: javax.swing Classi apparteneti a javax.swing La variabile d’ambiente CLASSPATH (1) • E’ una variabile di sistema che specifica dove è possibile collocare le classi. 1. In fase di compilazione indica le classi, appartenenti a package esterni, che si vogliono importare. 2. In fase di esecuzione indica dove è possibile posizionare le classi che devono essere utilizzate. • OSS. La variabile CLASSPATH deve: – sempre indicare la directory nella quale è installata la JDK – Puntare alla directory di livello direttamente superiore a quella indicante un package che si intende utilizzare. Importare un package. Ex. import java.net.*; public class WhoAmI { public static void main(String[] args) throws Exception { if(args.length != 1) { System.err.println( "Usage: WhoAmI MachineName"); System.exit(1); } InetAddress a = InetAddress.getByName(args[0]); System.out.println(a.getHostAddress()); } } La classe InetAddress appartiene al package java.net. Se tale package non fosse stato importato avremmo potuto scrivere in maniera equivalente: java.net.InetAddress a = java.net.InetAddress.getByName(args[0]); Creare un package Ex. FILE Useless.java package use; public class Useless { private String modificata; public String originale; public Useless(String org) { … } FILE UseUseless.java package use; public class UseUseless { public UseUseless() { } … } I due file devono trovarsi nella directory use Modificatori d'accesso • public : elementi (metodi, attributi) visibili dall’esterno e “applicabili” all’oggetto che istanzia la classe. • private : elementi non visibili dall’esterno. Possono essere occupati solo all’interno della stessa classe. • static : elementi che appartengono alla classe, non all’oggetto che la istanzia. Tutte le istanze della classe condividono un’unica copia del campo. – Ex.: • System.out out è un campo statico della classe System • double x = Math.pow(3,0.1) pow è un metodo statico della classe Math ● Se non è specificato nessun modificatore, i metodi sono visibili solo all’interno del package. public & private. Ex. public class Prima { private String modificata; public String originale; public Prima(String org) { … ● ● public class UsaPrima2 { … public static void main(String[] args) { Prima oggetto1 = new Prima( "primo oggetto inutile creato“ ); … System.out.println(oggetto1.originale); La variabile modificata è dichiarata di tipo private La variabile originale è dichiarata di tipo public GIUSTO System.out.println(oggetto1.modificata) ; … } } SBAGLIATO viene segnalato come errore in fase di compilazione Ereditarietà (1) ● Utilizzando la parola chiave extends è possibile creare delle sotto-classi di una classe padre. – – la parte dichiarata come public nella classe Padre viene ereditata dalla classe Figlio e diventa parte integrante della sezione public della nuova classe creata. la parte dichiarata come private nella classe Padre non viene ereditata. Resta una “esclusiva” della classe Padre. Ereditarietà. Ex.1 public class FiglioPrima extends Prima { private String messaggio; public String utilizzabile; public FiglioPrima (String msg) { super(msg); System.out.println(“Questo è il valore passato al costruttore di FiglioPrima” + msg); messaggio = msg; } public void showChild(int i){ for(int j=0; j<i; j++){ System.out.println(“Ripetizione di ”+ messaggio + “ numero ” + j); } } } Ereditarietà. Ex.1 package persona; public class Lavoratore extends Persona { String lavoro = "disoccupato"; public Lavoratore(String lavoro) { this.lavoro = lavoro; } public Lavoratore(String nome, String cognome, String lavoro) { super(nome, cognome); this.lavoro = lavoro; } public String getLavoro() { return lavoro; } public void setLavoro(String lavoro) { this.lavoro = lavoro; } } Ereditarietà – costruttori ● Ogni costruttore di una sotto-classe deve chiamare il costruttore della super-classe. – ● Il passaggio dei parametri alla classe padre avviene con la chiamata super(lista di parametri) Se non viene fatta una chiamata esplicita al costruttore, viene richiamato il costruttore di default. Ereditarietà. Ex.2 (1) public class UsaFiglioPrima { public UsaFiglioPrima() { } public static void main(String[] args) { FiglioPrima child1 = new FiglioPrima( "primo figlio inutile creato \n"); child1.showOriginale(); FiglioPrima child2 = new FiglioPrima( “secondo figlio inutile creato \n"); child2.showModificata(); child1.showChild(10); child2.showChild(3); } } Ereditarietà. Ex.2 (2) public class UsaFiglioPrima { public UsaFiglioPrima() { } public static void main(String[] args) { FiglioPrima child1 = new FiglioPrima( "primo figlio inutile creato \n"); child1.showOriginale(); FiglioPrima child2 = new FiglioPrima( “secondo figlio inutile creato \n"); child2.showModificata(); child1.showChild(10); child2.showChild(3); } Metodi ereditati dalla } Metodi propri della classe FiglioPrima classe padre Prima Esempio - UsaFiglioPrima E' stato creato un nuovo oggetto appartenente Valore passato al costruttore di FiglioPrima: primo figlio inutile creato E' stato creato un nuovo oggetto appartenente Valore passato al costruttore di FiglioPrima: secondo figlio inutile creato QUESTA E' LA STRINGA modificata Ripetizione di primo figlio inutile creato numero 0 Ripetizione di primo figlio inutile creato numero 1 Ripetizione di primo figlio inutile creato numero 2 Ripetizione di primo figlio inutile creato numero 3 Ripetizione di primo figlio inutile creato numero 4 Ripetizione di primo figlio inutile creato numero 5 Ripetizione di primo figlio inutile creato numero 6 Ripetizione di primo figlio inutile creato numero 7 Ripetizione di primo figlio inutile creato numero 8 Ripetizione di primo figlio inutile creato numero 9 Ripetizione di secondo figlio inutile creato numero 0 Ripetizione di secondo figlio inutile creato numero 1 Ripetizione di secondo figlio inutile creato numero 2 alla classe Prima primo figlio inutile creato alla classe Prima secondo figlio inutile creato FiglioPrima child1 = new FiglioPrima( "primo figlio inutile creato \n"); child2.showModificata(); child1.showChild(10); child2.showChild(3); Interfacce (1) • ● Le interfacce permettono di gestire e controllare gli oggetti in maniera più sofisticata [Bruce Eckel] Una classe potrebbe trovarsi nella condizione di dover ereditare metodi provenienti da diverse super-classi – ● In Java non è possibile avere più di una super-classe. Non è permesso dal linguaggio. – ● ● ● ● Si potrebbe presentare la necessità di trovarsi nel caso di ereditarietà multipla. Le motivazioni sono da ricercarsi nella elevata complessità ed a volte inefficienza dei compilatori che gestiscono la ereditarietà multipla. Le interfacce permettono di “raggruppare” i metodi. Contengono solo le firme dei metodi. Una classe può implementare più interfacce (proprio perché ci sono solo le firme dei metodi, non l’implementazione) Se una classe implementa una interfaccia “promette” che implementerà tale metodo. Interfacce (2) ● Le interfacce possono essere utilizzate da una classe con la keyword implements. public class NomeClasse implements NomeInterfaccia ● ● ● Tutte le classi che implementano una interfaccia devono implementare i metodi in essa presenti. Se una classe implementa una interfaccia, “promette” al compilatore che implementerà tali metodi. OSS: Come per le classi, il file che contiene l’interfaccia ha lo stesso nome dell’interfaccia stessa. Creare una Interfaccia Ex. MonsterActions.java public interface MonsterActions { void menace(); void destroy(); String chat(String sentence); } DragonActions.java public interface DragonActions { Flame spit(); void fly(); } Implementare una Interfaccia Ex. (1) class Ogre implements MonsterActions { … public Ogre(String breed){ … } public void menace(){ … } public void destroy(){ … } public String chat(String sentence){ return “BURP!”; } } Implementare una Interfaccia Ex. (2) class FrenchDragon implements MonsterActions, DragonActions{ … public FrenchDragon(Color clr){ … } public void menace(){ … } public void destroy(){ … } public String chat(String sentence){ return sentence.replace(‘r’, ‘v’); } public Flame split(){ … } public void fly(){ … } } Polimorfismo • Con il polimorfismo è possibile separare il cosa dal come. [Bruce Eckel] ● Permette di dare più forme ad uno stesso metodo. ● E’ possibile ridefinire il comportamento di un metodo mantenendo la stessa firma (overriding) ● E’ possibile dare una firma diversa, e quindi anche un comportamento, ad un metodo mantenendo lo stesso nome (overloading) Polimorfismo • Con il polimorfismo è possibile separare il cosa dal come. [Bruce Eckel] ● Permette di dare più forme ad uno stesso metodo. ● E’ possibile ridefinire il comportamento di un metodo mantenendo la stessa firma (overriding) ● E’ possibile dare una firma diversa, e quindi anche un comportamento, ad un metodo mantenendo lo stesso nome (overloading) Overriding ● ● In una sotto-classe, viene ridefinito un metodo già implementato nella super-classe. Dal lato del compilatore, nel caso di metodo overrided, viene sempre preso in considerazione quello appartenente alla classe gerarchicamente più interna. Overriding Ex. Shape public Shape draw(Point[] coord) public Shape move(Point displacement) for(i=o; i<points.length; i++){ points[i].x += displacement.x; points[i].y += displacement.y; } Circle public Shape move(Point displacement) center.x += displacement.x; center.y += displacement.y; Overloading ● ● ● ● Vengono definiti metodi con lo stesso nome ma firma diversa. In una sotto-classe può essere ridefinito un metodo già presente nella super-classe All’interno di una stessa classe si possono avere più overload dello stesso metodo. Dal lato del compilatore, il metodo con la firma specificata viene prima ricercato nella classe a cui appartiene l’oggetto che lo richiama, e se non presente nelle sue super-classi. Oveloading Ex. (1) Shape public Shape draw(Point[] coord) public Shape move(Point displacement) public Shape rotate(double rad_angle) Circle public Shape move(Point displacement) public Circle rotate() Oveloading Ex. (2) Shape public Shape draw(Point[] coord) public Shape move(Point displacement) public Shape rotate(double rad_angle ) public Shape rotate(int deg_angle ) L'interfaccia Cloneable (1) class TestClone implements Cloneable { int a; double b; TestClone cloneTest() { try { return (TestClone) super.clone(); } catch(CloneNotSupportedException e) { System.out.println("Clonaggio non permesso"); return this; } } } class CloneDemo { public static void main(String args[]) { TestClone x1 = new TestClone(); TestClone x2; x1.a = 10; x1.b = 20.98; x2 = x1.cloneTest(); // clone x1 System.out.println("x1: " + x1.a + " " + x1.b); System.out.println("x2: " + x2.a + " " + x2.b); } } L'interfaccia Cloneable (2) class TestClone implements Cloneable { int a; double b; public Object clone() { try { return super.clone(); } catch(CloneNotSupportedException e) { System.out.println("Clonaggio non permesso"); return this; } } } class CloneDemo2 { public static void main(String args[]) { TestClone x1 = new TestClone(); TestClone x2; x1.a = 10; x1.b = 20.98; x2 = (TestClone) x1.clone(); System.out.println("x1: " + x1.a + " " + x1.b); System.out.println("x2: " + x2.a + " " + x2.b); } } Le eccezioni ● ● ● Un’eccezione indica che si è verificato un errore durante l’esecuzione di un programma. Il sistema di gestione delle eccezioni in Java è basato sull’assunzione che il metodo che si accorge dell’errore non è in grado di gestirlo, ma lancia (throw) un’eccezione. Ci può essere un’altra porzione di codice che cattura(catch) l’eccezione e la gestisce. Blocco try-catch ● ● ● Si racchiude in un blocco try il codice che può lanciare eccezioni. Ci possono essere uno o più blocchi catch, che specificano il tipo di eccezione che possono gestire e contengono il codice per gestirla. Ci può essere un blocco finally che viene sempre eseguito, indipendentemente dal verificarsi dell’eccezione. Esempio try { int n = a/b; } catch(ArithmeticException e) { System.out.println(“Errore: divisione per zero.”); } Lanciare un'eccezione ● ● ● 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 un’eccezione viene lanciata, 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. Esempio di throw public class DivideByZeroException extend ArithmeticException{ }; public DivideByZeroException(){ super(“Tentativo di divisione per zero.”); } __________________________________________________ public double quoziente(double num,double den) throws DivideByZeroException{ if(den == 0){ throw new DivideByZeroException(); } return num / den; } Ancora sulle eccezioni ● Checked e Unchecked exception EccezioniDemo.java ● Stack delle eccezioni StackEccezioni.java Multi-threading ● ● ● ● Un thread è un singolo flusso sequenziale di controllo all'interno di un processo. Un singolo processo può avere diversi thread eseguiti in maniera concorrente. Ci sono molti usi possibli dei thread. In generale si usano quando non vogliamo che il flusso di esecuzione di un programma resti bloccato fino al termine di un evento o al rilascio di una risorsa(Es. Web crawling). Creiamo un thread associato a quell'evento o a quella risorsa e lo facciamo eseguire in maniera indipendente dal resto del programma. Multi-threading in Java (1) ● ● ● Il modo più semplice per creare un Thread è quello di estendere la classe java.lang.Thread Il metodo più importante per la classe Thread è run(), che va sovrascritto per farlo comportare esattamente come vogliamo. run( ) contiente il codice che sarà eseguito “simultaneamente” con gli altri thread in un programma. Multi-threading in Java (2) ● ● Il metodo start( ) nella classe Thread esegue delle operazioni di inizializzazione per il thread e poi chiama run( ). Quindi i passi da eseguire sono: ● ● ● ● il costruttore è invocato per costruire l'oggetto; successivamente chiama il metodo start( ) per configurare il thread; il meccanismo di esecuzione del thread chiama run( ). Se non richiamiamo start( ) sull'oggetto, il thread non partirà mai Esempio (1) public void run() { int count = (int)Math.round(Math.random()*1000); while(true) { System.out.println(count); if(--count==0) return; } } Multi-threading in Java (2) ● ● ● Se sappiamo di aver eseguito quello che era necessario fare nel nostro metodo run(), possiamo mandare un segnale allo scheduler dei thread ed avvisarlo che un altro thread può essere eseguito. Questo segnale prende la forma del metodo yield( ) Un altro modo in cui è possibile controllare i comportamento dei thread è attraverso la chiamata del metodo sleep( ) per un certo numero di millisecondi. Esempio (2) public void run() { int count = (int)Math.round(Math.random()*1000); while(true) { System.out.println(count); if(--count>=10) yield(); else return; } } Esempio (3) public void run() { int count = (int)Math.round(Math.random()*1000); while(true) { System.out.println(count); if(--count <= 10) return; try { sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } } } Multi-threading in Java (3) ● ● La priorità di un thread avvisa lo scheduler di quanto è importante il thread. Le prioritò possono essere impostate usando il metodo setPriority( ) della classe Thread. Mluti-threading in Java (3) ● ● ● In Java non è possibile implementare l'ereditarietà multipla Come fare se una classe è già sotto-classe di un'altra? L'interfaccia Runnable I/O ● ● ● InputStream e OutputStream (sottoclassi di Object) definiscono i metodi per le operazioni di I/O basate su byte L'I/O su file è fatto per mezzo delle classi FileInputStream e FileOutputStream. È possibile bufferizzare l'input e l'output attraverso le classi BufferedInputStream e BufferedOutputStream. I/O ● ● ● Reader e Writer servono per la gestione di flussi di caratteri. BufferedReader e BufferedWriter sono la loro versione bufferizzata. FileReader e FileWriter leggono e scrivono su file. La classe File ● Quattro costruttori: – public File(String nome) – public File(String path, String nome) – public File(File directory, String nome) – public File(URI uri) Esempio di lettura da file EsempioLetturaDaFile.java EsempioIOcompleto.java Strutture dati ● ● ● In java non ci sono i puntatori Necessità di struttura dinamiche (liste, alberi,...) Definizione di Nodo Nodo di una lista public class Nodo { private Object data; private Nodo nextNode; public Nodo( ); public Nodo( Object object ); public Nodo( Object object, Nodo node ); public Object getData(); public void setData(Object data) public Nodo getNext(); public void setNext( Node next ); } Lista Lista.java Classi utili per la manipolazione dei dati ● Vector (EsempioVector.java) ● Stack ● Hashtable (EsempioHashtable.java) ● Properties (EsempioScritturaFileProperty.java EsempioLetturaFileProperty.java) La programmazione generica ● ● ● Per le strutture dati (ArrayList, Vector, Map, Hashmap, etc) tutti gli oggetti vengono considerati di tipo Object Questo potrebbe creare dei problemi in caso di manipolazione degli elementi Con la programmazione generica questi problemi vengono superati La programmazione generica EsempioVectorGenerics.java EsempioHashtableGenerics.java Coppia.java Database e JDBC ● ● ● ● JDBC e' composto da varie classi che "cooperano" per fornire l'accesso ai dati del database. In prima linea viene il Driver, che interpreta tutte le funzioni richiamate e le 'traduce' per il database, il Driver deve essere caricato in memoria, una volta fatto questo è possibile utilizzarne le funzioni per creare una Connection, che incapsula il vero e proprio collegamento al database. Una Connection è necessaria per poter fare qualunque altra cosa. Una volta ottenuta la Connection siamo in grado di usare quest'ultima per produrre Statement, che verranno a loro volta usati per ottenere ResultSet, i quali contengono i dati. Non è sempre necessario l'uso di un ResultSet. Se vogliamo semplicemente eseguire delle modifiche sui dati (usando una UPDATE, INSERT o DELETE), possiamo usare il metodo executeUpdate() direttamente sullo Statement. Database e JDBC DatabaseUtil.java EsempioUsaDB.java Elementi di programmazione grafica ● Per mantenere la “promessa” di indipendenza dalla piattaforma, una applicazione Java, che presenta una Graphical User Interface, deve poter essere eseguita su piattaforme diverse senza dover modificare nulla nel bytecode. AWT ● ● ● ● AWT (Abstract Window Toolkit) è stata la prima libreria di classi presente in Java per la gestione di elementi grafici. Gestisce gli elementi grafici, delegandone la creazione e il comportamento alla piattaforma su cui sta girando l’applicazione. Vengono gestiti gli elementi propri della piattaforma (peer). PROBLEMI di portabilità – gli elementi grafici nativi delle diverse piattaforme hanno comportamenti differenti. – alcune piattaforme possono essere più ricche di componenti di altre SWING ● ● Con la libreria di classi Swing, tutti gli elementi vengono “dipinti” all’interno delle finestre create. L’unica funzionalità peer richiesta è la modalità di costruzione di una finestra ed il modo in cui disegnare in essa. ● Eredità alcune funzionalità di AWT. ● PROBLEMI: – ● L’esecuzione di una applicazione che utilizza una interfaccia Swing è molto più “pesante”. OSS: Nel seguito si farà riferimento alle classi Swing per la costruzione degli elementi grafici. JFrame ● ● ● Finestra top-level. Ossia una finestra non contenuta in altre finestre. E’ uno dei pochi elementi non disegnati. Le decorazioni (pulsanti, barra del titolo, icone, …) non sono disegnata da Swing ma dal sistema di gestione delle finestre proprio della piattaforma. Jframe Ex. import javax.swing.*; import java.awt.*; public class JustAFrame extends JFrame{ public JustAFrame(){ super(); System.out.println("Creazione di JustAFrame"); setTitle("Semplice Frame"); Image icn = Toolkit.getDefaultToolkit().getImage("dee3.jpg"); setIconImage(icn); } public static void main(String[] args){ JustAFrame jaf = new JustAFrame(); jaf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE ); jaf.setVisible(true); } } Altri elementi di SWING • JButton • JFileChooser • JLabel • JPanel • JScrollPane • JTextArea • JTextField • JToolTip Gerarchia degli elementi grafici Object Component Container JComponent Window Frame JToolTip JPanel JButton JFrame Disegnare i componenti in un JFrame … Container cp = getContentPane(); JButton but = new JButton(); cp.add(but); … Un Frame è strutturato in più “pannelli” Nel pannello dei contenuti - ContentPane – vengono disegnati i vari componenti Layout Permettono di impostare il posizionamento dei componenti grafici all’interno del Container (per esempio un JFrame o un JPanel). FlowLayout I componenti all’interno del contenitore vengono aggiunti orizzontalmente fino a quando non c’è più spazio. Dopo di che viene iniziata una nuova riga BorderLayout Il Container viene diviso in cinque aree: North, South, East, West, Center Semplice esempio di interfaccia NoEventFrame.java NoEventFrame2.java Gestione degli Eventi ● In una GUI, per poter rispondere ad una “azione” è necessario modellare il comportamento di tale evento. event-driven programming ● In Java il componente grafico, gli eventi ad esso associati ed il comportamento scaturito dal verificarsi dell’evento sono mantenuti separati. oggettoSorgenteEvento.addEventoListener(oggettoListenerEvento) ● oggettoListenerEvento istanzia una classe che implementa una interfaccia Listener L'interfaccia ActionListener ● E’ un’interfaccia della libreria standard ● Contiene solo il metodo actionPerformed(ActionEvent e) ● Viene richiamato quando si verifica un “evento di interesse” su un componente: – click del mouse su un JButton – pressione del tasto INVIO in un componente di testo – selezione di una voce in un menù ActionListener Ex. EventFrame.java EventFrameInnerClass.java EventFrameGestioneImplicita.java Window Builder Pro ● ● ● ● Plug-in di Eclipse WYSIWYG tool per la realizzazione di layout grafici Sviluppato da Google e rilasciato come prodotto Open Source Permette di sviluppare interfacce Swing, AWT, GWT ed SWT JEE Application server ● Si occupa della gestione delle applicazioni sviluppate con JEE ● Implementa le specifiche JEE ● Esempi: – Tomcat (Apache Software Foundation) – Jboss (Red Hat) – GlassFish (Oracle) – WebSphere (IBM) Servlet ● ● Devono implementare l'interfaccia Servlet I metodi dell'interfaccia servlet vengono invocati automaticamente dal servlet container – void init(ServletConfig config) – ServletConfig getServletConfig() – String getServletInfo() – void service(ServletRequest request, ServletResponse response) – void destroy() GenericServlet e HttpServlet ● Sono due classi astratte che implementano l'interfaccia Servlet ● javax.servlet.GenericServlet ● javax.servelt.http.HttpServlet – doGet(HttpServletRequest request, HttpServletResponse response) – doPost(HttpServletRequest request, HttpServletResponse response) Struttura di una applicazione JEE ● Radice – META-INF ● – MANIFEST.MF WEB-INF ● ● ● web.xml classes – File.class – Librerie.jar lib web.xml ● Contiene le informazioni relative all'applicazione: – Descrizione generale (display-name) – Descrizione (description) – Nome della servlet (servlet/servlet-name) – Descrizione della servlet (servlet/description) – Classe che deve essere eseguita (servlet/servlet-class) – Corrispondenza tra servlet e URL (servlet-mapping) Deploy di una applicazione ● ● Le applicazioni possono essere esportate ed importate come file compressi .war (Web Archive) L'application server si occupa di scompattare e fare il deploy dell'applicazione