CORSO DI LAUREA E DI DIPLOMA IN INFORMATICA UNIVERSITA’ DEGLI STUDI DI MILANO ANNO ACCADEMICO 1999-00 JAVA COME LINGUAGGIO PER LA PROGRAMMAZIONE CONCORRENTE E PER LA REALIZZAZIONE DI INTERFACCE GRAFICHE Gianfranco Prini DSI - Università di Milano [email protected] INTRODUZIONE MOTIVAZIONI, PEREQUISITI, ARGOMENTI PERCHE' JAVA IN UN CORSO DI SISTEMI OPERATIVI? • Strumento di laboratorio mediante il quale presentare e discutere esempi di programmazione concorrente (CP) • Strumento di laboratorio mediante il quale presentare e discutere esempi di programmazione di interfacce grafiche (GUI) PREREQUISITI • Saper creare file con un editor a caratteri (vi, emacs, etc.) • Saper realizzare programmi in ambiente compilativo (C, C++, PASCAL, etc.) • Saper navigare in Internet con un browser orientato alla GUI (Netscape, Explorer, etc.) JAVA E' UN LINGUAGGIO... • • • • • • • • sviluppato da Sun Microsystems in controtendenza rispetto al passato corredato da un ambiente di sviluppo portabile su varie piattaforme HW/SW orientato agli oggetti (OO) contenente primitive per CP progettato (anche) per realizzare GUI posizionato per l'editoria su Internet INDICE • • • • • • • • • Java: un tuffo nel linguaggio e nell'ambiente Introduzione a Java e HotJava Elementi di programmazione object-oriented Linguaggio Java:costrutti di base "La" microapplicazione in Java Trattamento delle eccezioni in Java Multithreading: programmazione concorrente Le applet e lo strumento appletviewer Primitive grafiche e programmazione di GUI CAPITOLO 1 JAVA: UN TUFFO NEL LINGUAGGIO E NELL'AMBIENTE "LA" MICROAPPLICAZIONE class Hello { public static void main (String args []) { System.out.println("Hello World!"); }} • • • • • Creare il file: Compilarlo: Si ottiene il file: Interpretarlo: L'output è: Hello.java javac Hello.java Hello.class java Hello Hello World! SPIEGAZIONI public static void main (String args []) – public rende il codice visibile al comando java (interprete) – static rende main invocabile anche in assenza di istanze della classe Hello (main è un attributo della classe Hello piuttosto che delle sue singole istanze) – void indica che main non ritorna nulla, il che è necessario per superare il type-checking del compilatore – args[] sono gli argomenti passati a main dalla shell quando si digita: java Hello arg1 arg2 ... argn System.out.println("HelloWorld!") – invoca il metodo println dell'oggetto out della classe System, che stampa la stringa sul file stdout APPLET • Miniapplicazione Java progettata per essere eseguita "all'interno di un (Web) browser" • Viene attivata dall'interno di un file HTML con <applet code=ClassName.class width=xxx height=yyy> <param name=ParamName value=Paramvalue> ..... <param name=ParamName value=ParamValue> AlternateContent </applet> • Deve essere dichiarata come estensione della classe Applet public class HelloApp extends Applet { ..... } LO STRUMENTO appletviewer • E' un "minibrowser" per file HTML: consente di creare ed eseguire applet in assenza di un browser vero e proprio (e.g. Mosaic, HotJava, Netscape, Explorer, etc.) • Crea una finestra di browsing comprendente un oggetto grafico (classe Graphics) a sua volta comprendente un'area grafica entro la quale operano le primitive di I/O (sia grafiche che alfanumeriche) invocate dalla applet • Oltre ai metodi della classe Applet, fornisce (nella GUI) un menu per controllare la applet ESEMPIO DI APPLET Nel file HelloApp.java inserire il codice import java.applet.Applet; import java.awt.Graphics; public class HelloApp extends Applet { public void paint (Graphics g) { g.drawString("Hello world!", 25, 25); } } Compilare con javac ottenendo HelloApp.class USO DI appletviewer • Nell'ambiente shell, è sufficiente digitare appletviewer [-debug] URL/file ..... • I tag diversi da <applet ...> presenti nei vari URL/file vengono semplicemente ignorati • Per ciascun tag <applet ...> si genera una finestrella corredata da un menu Applet • Ciascuna applet esegue le operazioni di I/O nella finestrella di propria competenza • L'utente può controllare l'esecuzione della applet selezionando funzioni dal menu Applet ESEMPIO DI ATTIVAZIONE DI APPLET VIA appletviewer Nel file HelloApplet.html inserire il codice <html> <applet code=HelloApp.class width=300 height=100> </applet> </html> Per attivare la applet digitare il comando appletviewer HelloApp.html e poi operare con il menu Applet della finestra IL MENU Applet DI appletviewer • Restart • Reload - esegue stop() seguita da start() - esegue stop() e destroy() e ricarica la applet (se ricompilata, ne carica la nuova versione) • Tag • Clone - mostra il tag che ha generato la applet - crea e avvia una nuova istanza della applet in una nuova finestra appletviewer • Info - mostra informazioni presenti nel file HTML • Properties - finestra di dialogo: consente di configurare i parametri di sicurezza e di accesso alla rete • Close - usa destroy() • Quit - chiude tutte le applet e termina appletviewer per terminare la applet e, se non ve ne sono altre, termina appletviewer JAVA E IL WEB DI INTERNET • HTML/WWW si limitano alla presentazione statica di testo e grafica con modalità ipertestuale in ambiente di rete • Java/HotJava estendono i servizi di rete alla presentazione di informazione multimediale (suono, video) e all'attivazione di programmi grafici e non CAPITOLO 2 INTRODUZIONE AL LINGUAGGIO JAVA E ALL'AMBIENTE HOTJAVA IL LINGUAGGIO JAVA • • • • • • • • • • Semplice ed estensibile (OO) Distribuito Interpretato Robusto Sicuro Architetturalmente neutrale Portabile A elevate prestazioni Concorrente (multithreaded) Dinamico SEMPLICE/ESTENSIBILE (OO) • Sintassi simile a C e C++ (facile da imparare) • Elimina i costrutti più "pericolosi" di C e C++ – – – – – • • • • aritmetica dei puntatori strutture (struct) definizione di tipi (typedef) preprocessore (#define) (de)allocazione esplicita della memoria Aggiunge garbage collection (GC) automatica Conserva la tecnologia OO di base di C++ Rivisita C++ in alcuni aspetti (W.Joy: C++--==) Interprete completo occupa 215 KB di RAM DISTRIBUITO E NEUTRALE • Incorpora molte funzionalità di rete (TCP/IP) • Comprende librerie di livello superiore (HTTP) • Rete facilmente accessibile (come i file locali) • • • • • Compilatore produce codice di tipo byte-code Byte-code indipendente da architettura HW Codice eseguibile su molte piattaforme HW Sviluppo: Solaris (SPARC), Win95 e NT (Intel) Disponibilità: le principali piattaforme HW/SW FLUSSO DEL CODICE Loader delle classi Sorgente Java Verifica del byte-code Interprete Compilatore Rete Generatore di codice Ambiente a run-time Byte-code Java Piattaforma hardware ROBUSTO • • • • • • • • • Rilevamento errori (compile-time e run-time) Type-checking (compile-time e run-time) Mascheramento dei puntatori all'utente Impossibilità di fare "casting" di puntatori Controllo automatico dei puntatori nulli Controllo automatico degli indici degli array Gestione delle eccezioni da parte dell'utente Verifica del byte-code prima dell'esecuzione Gestione della memoria (allocazione & GC) SICURO • • • • Dimostratore della correttezza del byte-code Rispetto garantito dei limiti dello stack Correttezza dei parametri delle istruzioni Legalità dell'accesso ai campi degli oggetti – pubblici – privati – protetti • Legalità di tutte le conversioni di tipo • In particolare, impossibilità di convertire numeri a puntatori, etc. PORTABILE, INTERPRETATO E A ELEVATE PRESTAZIONI • Formato dei dati specificato nei dettagli (p.es. gli interi sono di 32 bit e in complemento a 2) • Primitive grafiche astratte facilmente portabili agli ambienti Unix, Windows e Macintosh • Interpretazione abbrevia il ciclo di sviluppo • Circa 300.000 funcalls/sec (SPARCstation10) • Traduzione a run-time di byte-code in codice macchina fornirà prestazioni simili a C e C++ CONCORRENTE E DINAMICO • • • • Multithreading parte integrante del linguaggio Applicazioni interattive più facili a scriversi Migliore "reattività" (anche se non real-time) Esempio: caricamento asincrono di immagini nei browser di rete riduce i tempi di attesa • • • • Codice eseguibile anche in assenza di moduli Nuove release di moduli usabili a parità di API Nuovi protocolli caricabili da rete (download) Browser non più "centralisti" ma "federalisti" BROWSER "FEDERALISTA" • • • • • • • • • Client: Rete: Server: Rete: Client: Rete: Server: Rete: Client: richiesta oggetto da parte utente trasferimento richiesta al server reperimento oggetto nel database trasferimento oggetto al client rilevamento oggetto di tipo ignoto trasferimento informativa al server reperimento codice Java adeguato trasferimento codice Java al client visualizzazione oggetto richiesto L'AMBIENTE HOTJAVA • • • • Browser abilitato all'impiego di Java Manipola URL tradizionali Decodifica pagine HTML tradizionali Attiva programmi Java riferiti da pagine HTML • Programmi Java attivabili non solo via HTML • Quasi tutti i browser oggi sono Java-enabled • Gli altri browser ignorano i link a oggetti Java CAPITOLO 3 ELEMENTI DI PROGRAMMAZIONE OBJECT-ORIENTED PROBLEMI DEL SOFTWARE • • • • • • • • • Quantità sempre maggiori (informatizzazione) Sempre più complesso (e struttura non ovvia) Difficile da specificare (redazione "capitolati") Difficile costruirne di affidabile (robustezza) Difficile da collaudare (esaustività dei test) Difficile rimozione dei guasti (manutenibilità) Soggetto a continue modifiche (evoluzione) Modello di produzione "diffusa" (integrazione) Intrattabile con metodologie "centralistiche" OGGETTI: CHE SONO MAI? • • • • • • Versione informatica degli oggetti "reali" Dotati di una loro propria "individualità" Capaci di interagire per scambio di messaggi Caratterizzati da proprietà (dati e funzioni) Data abstraction: proprietà "statiche" (stato) Functional abstraction: proprietà "dinamiche" (astraggono il "comportamento" dell'oggetto) • Un msg modifica stato e attiva comportamenti • Un oggetto "è" una coppia [stato,funzioni] ESEMPIO: UN'AUTOMOBILE • Functional abstraction – Avvìati – Férmati – Gira a destra – Gira a sinistra • Data abstraction – – – – – Colore Velocità Rotazione volante Livello carburante Ultima revisione INCAPSULAMENTO • • • • • Associazione oggetto-coppia [stato,funzioni] Permette di "nascondere" aspetti della coppia Alcuni attributi sono visibili "all'esterno" Altri attributi sono "privati" dell'oggetto Le parti private sono reimplementabili senza implicazioni per gli interlocutori dell'oggetto • Propagazione delle modifiche assai contenuta • Stimolo al riutilizzo di oggetti ("black-box") • Nascita di un'industria di componenti SW ESEMPIO: AUTOMOBILE • Parti "visibili" (interfaccia pubblica): accesso a "ciò che l'auto può fare" – volante, combinazione volante-freno (ev. a mano) – blocchetto di accensione, oppure manovella – pedale dell'acceleratore, acceleratore automatico • Parti "nascoste" (implementazione): "come l'auto fa ciò che si può fare" – meccanica dello sterzo e dell'alimentazione – elettromeccanica dell'avviamento – sistema di alimentazione e accensione (IN)VISIBILITA' E PUREZZA • L'implementazione può essere cambiata a parità di interfaccia pubblica – presenza o meno del servosterzo – motorino di avviamento o piccola carica di dinamite – accensione elettromeccanica o elettronica • Approccio "puro": lo stato è privato, e lo si può modificare solo attraverso l'uso di quelle componenti funzionali che sono state dichiarate pubbliche (es. "férmati") • Approccio di Java: anche le componenti dello stato possono essere dichiarate pubbliche e modificate dall'esterno (es. "velocità=0") INTERAZIONI TRA OGGETTI • Gli oggetti possono comunicare e interagire mediante scambio di messaggi attraverso le loro interfacce pubbliche (stato o funzioni) • Per mezzo di un messaggio un oggetto può chiedere un'informazione a un altro oggetto, causarne un cambiamento di stato, oppure delegargli un'attività • Un messaggio in arrivo viene trattato dal metodo omonimo del ricettore, il quale "si attiva" per rispondere, per cambiare di stato, oppure per intraprendere un'attività ESEMPIO: UN'AUTOVETTURA • Il sistema antiskid durante una frenata invia periodicamente un messaggio alle ruote per "leggere" la loro velocità di rotazione • Il galleggiante nel serbatoio del carburante invia messaggi all'indicatore di livello sul cruscotto per "scrivervi" un nuovo stato • Il volante tornando alla posizione di riposo invia un messaggio al comando meccanico dell'indicatore di direzione per delegargli il compito di interrompere l'eventuale segnale lampeggiante (i.e. di "togliere la freccia") CLASSI • Visione "naturalistica" più che "insiemistica": insiemi di oggetti (gli esemplari della classe) aventi identica struttura (stato composto di identici attributi, identico comportamento) • Specificano sia le componenti dello stato (nome e tipo, ma non necessariamente il valore) che le operazioni possibili (non solo nome e tipo, ma anche il comportamento) • Due esemplari di una stessa classe sono distinguibili solamente per il valore dei loro attributi (il comportamento è sempre identico) SOTTOCLASSI E SOPRACLASSI • Sono rispettivamente la specializzazione e la generalizzazione di una classe per variazione del numero dei membri e/o per loro modifica • Una sottoclasse si ottiene per aggiunta, per occultamento o per ridefinizione di uno o più membri rispetto alla classe di partenza (che diventa una sopraclasse della nuova classe) • Gli oggetti della sottoclasse non "sanno" se sono nativi o se sono derivati da sopraclassi • NOTA BENE: in funzione del problema, sono possibili più tassonomie diverse, così come avviene nelle scienze naturali ESEMPIO: L'AUTOMOBILE • La classe "automobile" è generalizzabile alla sopraclasse "veicolo a motore", a sua volta generalizzabile alla sopraclasse "veicolo", a sua volta, generalizzabile alla classe "mezzo di trasporto", a sua volta ... (omissis) ... a sua volta generalizzabile alla classe "oggetto" • Oppure è specializzabile alla sottoclasse "berlina", a sua volta specializzabile alle sottoclassi "segmento A", "segmento B", etc. • Alternativamente, la classe "berlina" può essere specializzata alle sottoclassi "diesel", "a benzina", "elettrica", "a reazione", etc. EREDITARIETA' • E' il meccanismo di specializzazione che consente di derivare una sottoclasse (N.B.: non una sopraclasse!) da una classe data • Consente quindi il "riutilizzo programmabile" • Le componenti della classe originale vengono conservate nella classe derivata, a meno che in quest'ultima non vengano esplicitamente occultate (p.es. perché ritenute irrilevanti o "dannose") o ridefinite (p.es. perché se ne può fornire un'implementazione migliore) • Alle componenti della classe data se ne possono aggiungere altre a piacimento ESEMPI: GUI, MATRICI E 740 • Implementazione di un'interfaccia grafica – classe "finestra": attributo privato "sfondo" e metodo "cambia-sfondo" – sottoclasse "finestra-nera": attributo privato "sfondo" ridefinito con il valore costante "nero", metodo "cambiasfondo" occultato • Libreria di algebra lineare: – classe "matrice": metodo "determinante" generico – sottoclasse "matrice-diagonale": metodo "determinante" che moltiplica tra di loro gli elementi sulla diagonale • Compilatore della dichiarazione dei redditi – classe "contribuente": quadri del modello 740 base – classe "autonomi": aggiunta del membro "quadro-E" EREDITARIETA' MULTIPLA • Insieme di meccanismi (la letteratura non è univoca) che consentono di derivare nuove sottoclassi da due o più (sopra)classi • Esempio: due resistenze in serie possono essere viste come esemplare della classe "circuito" (o magari "circuito-serie-parallelo") o come esemplare della classe "resistenza" • Porzioni di codice diverse possono scegliere di trattare un oggetto secondo l'una o l'altra "vista", specificando qual'è la scelta corrente • Java non implementa ereditarietà multipla "NANETTO" DI PAOLO ERCOLI Al chiar.mo prof. Paolo Ercoli Direttore del Centro di Calcolo Sede Roma, 1.4.87 Caro Ercoli, nella mia qualità di presidente del corso di laurea in Ingegneria Informatica mi trovo a lamentare il disservizio... (omissis) ... Con i migliori saluti. Paolo Ercoli CLASSI ASTRATTE • Create per generalizzazione, rappresentano descrizioni "incomplete" di oggetti • Raccolgono alcune delle loro caratteristiche comuni, ma non in quantità sufficiente a farne delle vere e proprie superclassi • Pertanto non posseggono esemplari ("non possono essere istanziate"), ma è possibile derivarne sottoclassi "vere" (i.e. non astratte) • Usate principalmente come strumenti di polimorfismo per definire operazioni (e.g. "print") comuni a più classi poco correlate TERMINOLOGIA E SINONIMI • Classi o tipi – generalizzazione, specializzazione o raffinamento – sottoclasse o figlia, sopraclasse (o superclasse) o madre o classe base, classe astratta – ereditarietà [ingl. "inheritance"], gerarchia o tassonomia di classi • Oggetti o attori – esemplare [gerg. "istanza", da "instance"] di una classe – componente o membro o proprietà • Funzioni o operazioni – astrazione funzionale o comportamento (behaviour) – componente pubblica o interfaccia o metodo • Dati o attributi – stato [il termine "data abstraction" è mal traducibile] CAPITOLO 4 LINGUAGGIO JAVA: COSTRUTTI DI BASE ALFABETO • Java adotta la codifica standard Unicode della società Unicode, Inc. (ftp://ftp.unicode.org) definito in: The Unicode Standard, Worldwide Character Encoding, Version 2.0 • I programmi Java possono essere scritti con altre codifiche (e.g. la codifica ASCII a 7 o 8 bit), ma devono essere convertiti alla codifica Unicode (a 16 bit) prima di essere utilizzati da parte di compilatori, interpreti, debugger, etc. • N.B. - Nello standard Unicode, un segmento della codifica è riservato ai caratteri speciali CODICE SORGENTE • Consiste di una o più unità di compilazione • Ogni unità può contenere (oltre ai commenti) – – – – al più una istruzione package una o più istruzioni import una o più dichiarazioni di classe (class) una o più dichiarazioni di interfaccia (interface) • Per ciascuna unità di compilazione, al più una classe può essere dichiarata public • Il codice sorgente viene compilato a bytecode (cfr. The Java Virtual Machine Specification), un insieme di istruzioni machine-independent COMMENTI • Presenti in tre diversi stili, non hanno alcuna influenza sulla semantica dei programmi – // Primo stile: io sono un commento su di una sola linea – /* Secondo stile: anch'io sono un commento monolinea */ – /* Secondo stile: io, invece, sono un commento più lungo: non ci sto in una sola linea e quindi ne occupo ben due */ – /** Terzo stile: io sono un commento di tipo speciale, che chiamano "commento di documentazione". */ • Un commento del terzo tipo va collocato solo immediatamente prima di una dichiarazione (di classe, di interfaccia, di costruttore o di membro); viene incluso nella documentazione generabile automaticamente (ex sorgente) TIPI SEMPLICI "Non tutti i dati sono oggetti" (impurità di Java) • boolean - tipo enumerativo (due elementi) • char - carattere di 16 bit (Unicode 1.1.5) • byte - intero di 8 bit (complemento a 2) • short - intero di 16 bit (complemento a 2) • int - intero di 32 bit (complemento a 2) • long - intero di 64 bit (complemento a 2) • float - floating-point di 32 bit (IEEE 754) • double - floating-point di 64 bit (IEEE 754) Tutti i tipi semplici (o di base) sono predefiniti TIPI COMPOSTI • Equivalenti alle variabili strutturate PASCAL, nella loro versione dinamica (operatore new) • I dati composti sono mediati, i.e. manipolati per mezzo di puntatori non visibili all'utente (i dati semplici sono immediati, i.e. manipolati direttamente) • Tre categorie di tipi composti – Matrici - versione dinamica degli array PASCAL – Classi - versione "attiva" dei record PASCAL – Interfacce - simili alle dichiarazioni forward in PASCAL • Di questi, solo i tipi matrice sono predefiniti: le librerie di classi e di interfacce non lo sono LETTERALI (1) • Rappresentazione "esterna" di dati e oggetti • Alcuni tipi semplici ammettono letterali – boolean – char – – – – int long float double - true, false 'a', '\u03ff', '\037', '\x7f' '\', '\n', '\t', '\b', '\r', '\f', '\\', '\'', '\"' 127, 0177, 0x7F, 0X7F, 0x7f, 0X7f 127L, 127l, 2147483648 3.14, 3.1E12, 3.1e-12, .1e12, 2e-12 3.14D, 3.14d, 3.1e-12D, .1e12d, 2e-12D • Uno solo dei tipi composti ammette letterali – String - "", "Da\ncapo", "Io non sono Luigi Stringa" • Per gli altri esiste il letterale generico null LETTERALI (2) • Letterali distinti possono rappresentare lo stesso valore – int - 127, 0177, 0x7F • I numeri negativi, di qualunque tipo siano (salvo gli esponenti), non sono esprimibili mediante letterali • Le routine di stampa sono in grado di stampare qualunque dato di tipo semplice • Il formato di stampa è coerente con quello dei letterali (se esiste); nel caso di più formati possibili, ne viene scelto uno come standard PAROLE CHIAVE (RISERVATE) • Parole chiave: abstract, boolean, break, byte, case, catch, char, class, const (*), continue, default, do, double, else, extends, final, finally, float, for, goto (*), if, implements, import, instanceof, int, interface, long, native, new, package, private, protected, public, return, short, static, super, switch, synchronized, this, throw, transient (*), try, void, volatile, while (*) Inutilizzata nella specifica attuale di Java IDENTIFICATORI • Debbono iniziare con una lettera (v. sotto) o con uno dei due simboli '_' e '$', e possono contenere qualunque carattere non speciale della codifica Unicode; non hanno (in pratica) limiti di lunghezza • Ai fini di Java, sono lettere – tutti i caratteri compresi tra 'A' e 'Z' e tra 'a' e 'z' – le non-cifre di codice Unicode superiore a 00C0 (hex) • Esempi: identifier, user_name, User_name, _user_name, $user_name, user$name1 • Se attributi di classi, sono inizializzati a false (i boolean), 0 (i tipi numerici) o null (il resto) MATRICI • Vettori monodimensionali di dati, semplici o composti, di tipo omogeneo – Semplici - char a[]; char[] b; char array[]; – Composti (oggetti) - String args[]; String[] other_args; – Composti (matrici) - char chess[][]; char[][] checkers; Voxel human_body[][][]; • Indicizzati con int (indice primo elemento = 0), con controllo di validità degli indici a run-time • Vanno create e dimensionate esplicitamente, anche contestualmente alla dichiarazione (la quale di per sé non alloca nulla, ma si limita a definire il tipo di un nome, inizializzato a null) MATRICI: CREAZIONE INIZIALIZZAZIONE • Dichiarazione e successiva creazione int array[][]; array = new int[10][3]; /* qui array == null */ • Dichiarazione e contestuale creazione int array[][] = new int[10][3]; • Dichiarazione e parziale creazione int array[][] = new int[10][]; • Dichiarazione, creazione e inizializzazione – String names[] = {"Tic","Tac"} /* equivalente a ... */ – String names[] = new String[2]; names[0] = "Tic"; names[1] = "Tac"; ERRORI CON LE MATRICI • Tentare di dimensionare una matrice nella (e non contestualmente alla) sua dichiarazione int list [50]; • Tentare di inizializzare una matrice prima di averla creata int list[]; for (int i=0 ; i<9 ; i++) { list[i] = i; } • Prima della sua creazione (operatore new) la matrice non esiste: la dichiarazione ha l'unico scopo di specificare il tipo della variabile (che comprende solo il numero delle dimensioni) MATRICI COME CLASSI • Dalla classe Object, la capostipite di tutte le classi, deriva la classe Array, dotata di un metodo length ereditato dalle sue sottoclassi int a[][] = new int[10][3]; a.length; a[0].length; /* 10 */ /* 3 */ • Per ogni tipo (semplice o composto) esiste implicitamente una sottoclasse di Array che comprende tutte le matrici di oggetti di quel tipo (N.B. da Array non si possono derivare sottoclassi esplicitamente) • Se B è sottoclasse di A, allora B[] lo è di A[] CLASSI, ATTRIBUTI E METODI • Esempio di classe public class MyClass { int i; /* attributo */ public MyClass () { /* metodo costruttore: ha lo i = 10; stesso nome della classe */ } public void Add_to_i (int j) { /* altro metodo */ i = i+j; } } • Ricordiamo che Java non adotta il modello a oggetti puro: "non tutti i dati sono oggetti" FUNZIONI E POLIMORFISMO: OVERLOADING DI METODI • Variante dell'esempio precedente public class MyNewClass { int i; public MyNewClass () { i = 10; } public MyNewClass (int j) { i = j; } ..... } /* attributo */ /* metodo costruttore: ha lo stesso nome della classe */ /* altro metodo costruttore diverso dal precedente */ • Metodi omonimi devono essere distinguibili per la quantità e/o per il tipo degli argomenti ATTRIBUTO this • Implicitamente presente in ogni oggetto, è sempre legato all'oggetto medesimo public class MyNewClass { int i; public MyNewClass () { i = 10; } public MyNewClass (int i) { this.i = i; } ..... } /* attributo */ /* parametro */ /* disambiguazione */ • Risolve omonimie e.g. tra attributi e parametri CREAZIONE DI OGGETTI • Creazione e uso di un oggetto con MyClass MyClass mc; mc = new MyClass(); mc.i++; mc.Add_to_i(10); /* dichiarazione, non creazione */ /* creazione: l'attributo i vale 10 */ /* ora i vale 11 */ /* e ora i vale 21 */ • Creazione di un oggetto con MyNewClass MyNewClass mc0, mc1; /* dichiarazione, non creazione */ mc0 = new MyNewClass(); /* creazione: l'attributo i vale 10 */ mc0.i++; /* ora i vale 11 */ mc1= new MyNewClass(20); /* creazione: l'attributo i vale 20 */ mc1.i++; /* ora i vale 21 */ DISTRUZIONE DI OGGETTI • Java non supporta "distruttori" espliciti: gli oggetti non si distruggono, si "riciclano" • Un oggetto privo di puntatori incidenti non è più accessibile alle applicazioni e la memoria che esso occupa può essere "riciclata" String s; s = new String ("abc"); s = "def"; /* dichiarazione, non creazione */ /* creazione: s punta a "abc" */ /* "abc" non è più puntata da s */ • Il "riciclatore" (garbage collector, o GC) opera in un thread indipendente (i.e. "in parallelo" con altri thread, sia di utente che di sistema) FINALIZZATORI DI OGGETTI • Un oggetto "riciclabile" (i.e. privo di puntatori incidenti) potrebbe trovarsi in uno stato poco "pulito" (e.g. in passato potrebbe aver aperto dei file che non sono stati ancora chiusi) • Prima di procedere alla fase cruenta, il GC invoca il metodo finalize di ciascun oggetto "riciclabile", definibile da utente protected void finalize () { close (); } /* per protected vedi oltre */ /*chiudi tutti i file aperti */ • Il metodo finalize esiste sempre: se non è stato ridefinito viene ereditato da Object CLASSI: SINTASSI [Doc comment][Modifiers] class ClassName [extends SuperClassName] [implements InterfaceName [, InterfaceName]] {ClassBody} Doc comment Modifiers extends implements ClassBody - commento "di documentazione" - uno o più dei qualificatori abstract, final, public/protected/private, native, synchronized, transient, volatile - la classe è sottoclasse di un'altra (e di una sola: ereditarietà singola) - la classe realizza una o più interfacce (può "simulare" ereditarietà multipla) - gli attributi e i metodi della classe CLASSI E SOTTOCLASSI • Le zebre come particolari tipi di cavallo... public class Horse { int Head, Tail, Legs, Body; public Horse () { Head = 1; Tail = 1; Legs = 4; Body = 1; } public void AddLegs (int Legs) { this.Legs += Legs;} } public class Zebra extends Horse { int Stripes; public Zebra (int Stripes) { this.Stripes = Stripes; } public void AddLegs (int Legs) /* ridefinizione */ { this.Legs += Legs + Stripes; } } SOTTOCLASSI E super • Manipoliamo le zampe di una nuova zebra Zebra mz; mz = new Zebra(1000000000); mz.AddLegs(4); /* ha 4 zampe */ /* ora ne ha 1000000008 */ • Il vecchio metodo AddLegs è ancora usabile mz.super.AddLegs(4); /* ora ne ha 1000000012 */ • L'attributo super, implicitamente presente in ogni oggetto, permette di "ricuperare" un attributo/metodo da una (sopra)classe dopo che è stato ridefinito in una sua (sotto)classe SOTTOCLASSI E CASTING • Proseguendo con l'esempio precedente Horse mh = (Horse)mz; mh.AddLegs(4); (Zebra)mh.AddLegs(4); /* ora è vista come cavallo */ /* ora ha 1000000016 zampe */ /* ora ne ha 2000000020 */ • Il cast da una classe a una sottoclasse (anche non diretta) è possibile se l'oggetto è davvero un esemplare della sottoclasse (il controllo è fatto a run-time); il viceversa è sempre OK • Il cast per linea di discendenza non diretta è un errore (il controllo è fatto a compile-time) • Il cast non altera gli oggetti: influisce solo sul modo di "osservare" un puntatore all'oggetto METODI: SINTASSI [Doc comment][Modifiers] ReturnType MethodName (ParameterList) {MethodBody} Modifiers ReturnType ParameterList MethodBody - uno o più dei qualificatori abstract, final, public/protected/private, native, synchronized, transient, volatile - va omesso nei costruttori, ma va indicato (eventualmente void) negli altri casi; deve essere identico al tipo ritornato da metodi sovrascritti - deve essere coerente con quella dei metodi sovrascritti - le variabili locali devono essere inizializzate prima di essere usate ACCESSI E CONDIVISIONE • Quattro tipi di diritti d'accesso – public – protected – private – void AnyOneCanAccess void OnlySubclassesCanAccess void NoOneElseCanAccess void OnlyFromWithinMyPackage () { ... } () { ... } () { ... } () { ... } L'ultimo tipo si chiama "friendly" • Attributi statici: condivisi da tutte le istanze; metodi statici: operano solo su dati statici class NewDocument extends Document { static int Version = 10; int Chapters; static void NewVersion () { Version++; } static void AddChapter () { Chapters++; } } /* OK */ /* KO */ TIPI DI CLASSE • Quattro tipi di classi – abstract: tra i vari metodi, deve contenerne almeno uno abstract, ma non può contenere metodi private o static; deve dare origine a sottoclassi; non può essere istanziata – final: termina una catena di classi-sottoclassi, non può dare origine a ulteriori sottoclassi – public: può essere usata senza formalità nel package che ne contiene la dichiarazione; disponibile anche in altri package, purché vi venga "importata" – synchronized: tutti i metodi interni sono synchronyzed • Classi astratte public abstract class Graphics { /* generica */ public abstract void DrawLine(int x1,y1,x2,y2); } public class VGA extends Graphics { /*specifica */ public void DrawLine(int x1,y1,x2,y2) { <codice per VGA> }} INTERFACCE • Alternativa alle classi astratte: non richiede la derivazione esplicita di sottoclassi public interface AudioClip { void play (); /* avvia i'esecuzione */ void loop (); /* esegui ciclicamente una audio clip */ void stop (); } /* interrompi l'esecuzione */ class MyAudio implements AudioClip { void play () { <codice che implementa play> } void loop () { <codice che implementa loop> } void stop () { <codice che implementa stop> } } class YourAudio implements AudioClip { <codice> } • I metodi possono essere public o abstract, gli attributi public, static o final OPERATORI E PRECEDENZA • Operatori (ordine di precedenza decrescente): . [] () ++ -! ~ instanceof * / % + /* anche: String name = "Luigi" + "Stringa" */ << >> >>> < > <= >= == != /* ritornano un booleano */ & ^ | && || ? ... : ... = += -= *= /= &= |= ^= %= <<= >>= >>>= ISTRUZIONI CONDIZIONALI • If – if (boolean) { statements; } else { statements; } • Case – switch (expr) { case tag1: statements; break; ..... case tagn: statements; break; default: statements; break; } ISTRUZIONI ITERATIVE • For – for (init expr1 ; test expr2 ; incr expr3) { statements; } • While – while (boolean) { statements; } • Do – do { statements; } while (boolean) • Controllo di flusso – – – – break [label] continue [label] return expr; label: statement FOR, SWITCH, CONTINUE E BREAK: PRECISAZIONI label: for (int i =0 , int j=0 ; i<10 && j<20; i++ , j++) { /* exp */ for (int z=0 ; z<100 ; z++) { /* scope è solo il for */ switch (expr) { case tag: statements; break; /* prosegue con penultima riga */ ..... default: statements; break label; } /* prosegue da label */ if (z==15) continue; /* prosegue il for z */ if (z==i+j) continue label; /* prosegue da label */ } } CAPITOLO 5 "LA" MICROAPPLICAZIONE: COME LA SI SCRIVE IN JAVA "LA" MICROAPPLICAZIONE class Hello { public static void main (String args []) { System.out.println("Hello World!"); }} • • • • • Creare il file: Compilarlo: Si ottiene il file: Interpretarlo: L'output è: Hello.java javac Hello.java Hello.class java Hello Hello World! SPIEGAZIONI public static void main (String args []) – public rende il codice visibile al comando java (interprete) – static rende main invocabile anche in assenza di istanze della classe Hello (main è un attributo della classe Hello piuttosto che delle sue singole istanze) – void indica che main non ritorna nulla, il che è necessario per superare il type-checking del compilatore – args[] sono gli argomenti passati a main dalla shell quando si digita: java Hello arg1 arg2 ... argn System.out.println("HelloWorld!") – invoca il metodo println dell'oggetto out della classe System, che stampa la stringa sul file stdout ERRORI DI COMPILAZIONE E DI ESECUZIONE javac: Command not found – la variabile path della shell non include la directory in cui si trova il compilatore javac (analogamente per java) System.out.printl ("HelloWorld!) ^ – errore di stumpa:il metodo si chiama println, non printl In class Hello: main must be public and static – ci si è dimenticati di dichiarare main come static Can't find class Hello – errore di stumpa: nel file Hello.java la classe è stata dichiarata erroneamente p.es. con il nome di Helllo, e il compilatore ha creato un file di nome Helllo.class, che l'interprete non può trovare se si è digitato: java Hello PACKAGE E DIRECTORY • Alcuni package disponibili con il JDK – java.applet: classe Applet e tre interfacce (AppleContext, AppleStub, AudioClip) – java.awt: widgets per creare GUI (classi Graphics, Button, Choice, Menu, Component, Panel, TextArea, TextField) – java.io: classi di I/O (FileInputStream, FileOutputStream) – java.lang: classi base del linguaggio (Object, Thread, Exception, System, Integer, Float, Math, String, etc.) – java.net: classi a supporto delle applicazioni di rete (Socket, URL, URLConnection) – java.util: classi miste (Date, Dictionary, Random, Stack) • Il package java.packagename si trova nella directory java/packagename, e in essa vi si trovano i file con le classi (Classname.class) PACKAGE E IMPORTAZIONI • E' necessario importare le classi che si intendono utilizzare: – import java.util.Date (la sola classe Date del package java.util, che si trova nel file java/util/Date.class) – import java.awt.* (tutte le classi del package java.awt, ossia tutti i file java/awt/*.class) • Se un file di nome nome.java contiene la linea package nome1. ... .nomen il compilatore ne mette il codice eseguibile nel file di pathname nome1/.../nomen/nome.class, altrimenti lo mette nella stessa directory del file sorgente (il package di default, senza nome) e la classe può essere importata con import nome CAPITOLO 6 LA GESTIONE DELLE ECCEZIONI IN JAVA ECCEZIONI E catch/throw • Consentono di realizzare goto non locali void GrowZebra(Zebra mz) { try { for (;;) {FeedZebra(mz, new Anchovy()) ;}} catch (JunkFoodException e) { mz.Starve(); } catch (ThrowUpException e) { mz.Drink(new Digestive()); } } void FeedZebra(Zebra z, Anchovy a) { Exception away = new JunkFoodException(); Exception up = new ThrowUpException(); if (a.smells()) { throw away; } else if (z.full()) { throw up; } else { z.GiveAnchovy(a); } } ECCEZIONI PREDEFINITE E DEFINIZIONE DI ECCEZIONI • Eccezioni predefinite e ricuperabili ArithmeticException IllegalArgumentException ArrayStoreException IllegalMonitorStateException ClassCastException IllegalThreadStateException NullPointerException IndexOutOfBoundException NumberFormatException NegativeArraySizeException SecurityException • Definizione di nuove eccezioni ricuperabili class JunkFoodException extends Exception { JunkFoodException() {} } CAPITOLO 7 JAVA: MULTITHREADING PROGRAMMAZIONE CONCORRENTE E PROGRAMMAZIONE MULTITHREAD public class Multithread { public static void main (String args[]) { TestThrd t1, t2, t3; t1 = new TestThrd("Din"; (int)(Math.random())*2000); t2 = new TestThrd("Don"; (int)(Math.random())*2000); t3 = new TestThrd("Dan"; (int)(Math.random())*2000); t1.start(); t2.start(); t3.start(); } class TestThrd extends Thread { private String whoami; private int delay; public TestThrd(String s, int d) { whoami = s; delay = d; } public void run() { try { sleep(delay); } catch (InterruptedException e) {} ; System.out.println(whoami) ; } } CAPITOLO 8 LE APPLET DI JAVA E LO STRUMENTO appletviewer APPLET • Miniapplicazione Java progettata per essere eseguita "all'interno di un (Web) browser" • Viene attivata dall'interno di un file HTML con <applet code=ClassName.class width=xxx height=yyy> <param name=ParamName value=Paramvalue> ..... <param name=ParamName value=ParamValue> AlternateContent </applet> • Deve essere dichiarata come estensione della classe Applet public class HelloApp extends Applet { ..... } LA CLASSE Applet: RELAZIONI CON LA GERARCHIA JAVA Tre classi intermedie tra Object e Applet • java.lang.Object: capostipite di tutte le classi • java.awt.Component: metodi per gestire gli eventi e per "disegnare" linee, curve, bottoni, menu, immagini, etc. • java.awt.Container: metodi per "raccogliere" oggetti di classe Component in "contenitori" e per gestirne il posizionamento (layout) • java.awt.Panel: l'unica non abstract delle tre • java.awt.Applet: capostipite di tutte le applet, LO STRUMENTO appletviewer • E' un "minibrowser" per file HTML: consente di creare ed eseguire applet in assenza di un browser vero e proprio (e.g. Mosaic, HotJava, Netscape, Explorer, etc.) • Crea una finestra di browsing comprendente un oggetto grafico (classe Graphics) a sua volta comprendente un'area grafica entro la quale operano le primitive di I/O (sia grafiche che alfanumeriche) invocate dalla applet • Oltre ai metodi della classe Applet, fornisce (nella GUI) un menu per controllare la applet METODI USATI DA appletviewer Ereditati da Applet ("vuoti" se non sovrascritti) • init() - chiamata dopo il caricamento della applet • start() - chiamata quando una applet viene visitata • stop() - chiamata quando l'applet va fuori schermo • destroy() - chiamata a fine ciclo di vita della applet Ereditati da Component (g di classe Graphics) • paint(g) - disegna una scatola grigia nella finestra • update(g) - cancella e ridisegna la scatola nella finestra ESEMPIO DI APPLET Nel file HelloApp.java inserire il codice import java.applet.Applet; import java.awt.Graphics; public class HelloApp extends Applet { public void paint (Graphics g) { g.drawString("Hello world!", 25, 25); } } Compilare con javac ottenendo HelloApp.class USO DI appletviewer • Nell'ambiente shell, è sufficiente digitare appletviewer [-debug] URL/file ..... • I tag diversi da <applet ...> presenti nei vari URL/file vengono semplicemente ignorati • Per ciascun tag <applet ...> si genera una finestrella corredata da un menu Applet • Ciascuna applet esegue le operazioni di I/O nella finestrella di propria competenza • L'utente può controllare l'esecuzione della applet selezionando funzioni dal menu Applet ESEMPIO DI ATTIVAZIONE DI APPLET VIA appletviewer Nel file HelloApplet.html inserire il codice <html> <applet code=HelloApp.class width=300 height=100> </applet> </html> Per attivare la applet digitare il comando appletviewer HelloApp.html e poi operare con il menu Applet della finestra IL MENU Applet DI appletviewer • Restart • Reload - esegue stop() seguita da start() - esegue stop() e destroy() e ricarica la applet (se ricompilata, ne carica la nuova versione) • Tag • Clone - mostra il tag che ha generato la applet - crea e avvia una nuova istanza della applet in una nuova finestra appletviewer • Info - mostra informazioni presenti nel file HTML • Properties - finestra di dialogo: consente di configurare i parametri di sicurezza e di accesso alla rete • Close - usa destroy() • Quit - chiude tutte le applet e termina appletviewer per terminare la applet e, se non ve ne sono altre, termina appletviewer METODI DI Applet: QUANDO SOVRASCRIVERLI • init() - quando si debbano effettuare inizializzazioni particolari e non di pertinenza del costruttore della applet (p.es. qualora si debbano creare dei thread di animazione da avviare più tardi) • start() stop() - quando si vogliano avviare/sospendere le attività della applet in funzione della sua esposizione sullo schermo (e.g. per avviare o arrestare i thread di animazione quando la finestra diventa esposta o nascosta) • destroy() - quando, dopo l'ultima stop(), la applet debba esser distrutta, ma prima di fare ciò sia utile annullare l'effetto delle inizializzazioni (p.es. per distruggere i thread di animazione, che altrimenti rimarrebbero sospesi per sempre) DELEGA A NUOVI THREAD DI ATTIVITA' "UNA TANTUM" Per caricare un oggetto di classe AudioClip public void start() { ... /*codice specifico per la applet */ if (onceThread == null) { onceThread = new Thread(this); onceThread.start(); } } public void run() { ... /*codice specifico per la applet */ if (Thread.currentThread == onceThread) { myAudio = getAudioClip( ... ); } Immagini GIF/JPEG caricate da thread separati DELEGA A NUOVI THREAD DI ATTIVITA' RIPETITIVE public void start() { ... /*codice specifico per la applet */ if (loopThread == null) { loopThread = new Thread(this); loopThread.start(); } public void stop() { loopThread = null; } public void run() { ... /*codice specifico per la applet */ while (Thread.currentThread == loopThread) { ... } } METODI DI Component: QUANDO SOVRASCRIVERLI • paint(g) - quando si debba presentare un pannello più update(g) sofisticato di un rettangolo con fondo grigio import java.awt.*; import java.applet.*; public class GraphicsApplet extends Applet { public void paint(Graphics g) { Dimension r = size(); g.setColor(Color.red); g.drawRect(10, 10, r.width-20, r.height-20); System.out.println ("paint called"); /* va su stdio */ } } PASSAGGIO DEI PARAMETRI DA FILE HTML A CLASSI JAVA public void init() { String fontsize = getParameter("fontsize"); if (fontsize=null) { fontsize=12; } else { fontsize = Integer.parseInt(fontsize); } } <applet code=ResizeHelloApp.class height=200 width=400> <param name=fontsize value=16> Applets can be viewed with Java-powered browsers only </applet> CAPITOLO 9 JAVA: PRIMITIVE GRAFICHE E PROGRAMMAZIONE DI GUI CLASSE Component E SUE SOTTOCLASSI Non tratta i menu (MenuComponent e derivate) • Controlli fondamentali: Button, Checkbox (e CheckBoxGroup), Choice, List, TextField • Acquisizione di input da utente: Scrollbar, TextArea • Componenti personalizzate: Canvas • Frasi esplicative: Label • Contenitori: Container con sottoclassi Panel e Window, quest'ultima con sottoclassi Frame, e Dialog (con sottoclasse FileDialog) TextField, TextArea estendono TextComponent CLASSE MenuComponent E SUE SOTTOCLASSI • Sottoclasse diretta della classe Object, in quanto le funzioni dei menu sono spesso limitate dalla piattaforma ospite, e sarebbe poco appropriato derivarli da Component • Controlli fondamentali: MenuItem, con sottoclassi CheckBoxMenuItem e Menu • Menu di menu: MenuBar, che possono essere inserite solamente in oggetti di classe Frame EVENTI E LORO CODIFICA • Quando l'utente agisce su una componente, viene generato un evento (oggetto di classe Event) che viene passato come argomento al metodo di gestione degli eventi (handleEvent) di quella componente • Gli oggetti di tipo Event contengono – – – – – – oggetto che ha "subito" l'evento timbratura (istante di occorrenza) dell'evento tipo dell'evento (bottone del mouse premuto o rilasciato) coordinate dell'evento (all'interno della componente) tasto premuto (solo per eventi generati dalla tastiera) stato dei tasti modificatori (Shift, CTRL, ALT, etc.) METODI PER LA GESTIONE DI EVENTI E LORO TIPO • • • • • • • • • • • • action(Event.ACTION_EVENT) mouseEnter(Event.MOUSE_ENTER) mouseExit(Event.MOUSE_EXIT) mouseMove(Event.MOUSE_MOVE) mouseDown(Event.MOUSE_DOWN) mouseDrag(Event.MOUSE_DRAG) mouseUp(Event.MOUSE_UP) keyDown(Event.KEY_PRESS) keyUp(Event.KEY_UP) gotFocus(Event.GOT_FOCUS) /* per componenti */ lostFocus(Event.LOST_FOCUS) /* attivabili da KBD */ handleEvent(<qualunque tipo di evento>) GESTIONE DEGLI EVENTI • All'ocorrenza di un evento, il corrispondente oggetto di tipo Event viene passato al metodo handleEvent (ridefinibile da utente), il quale a sua volta invoca il metodo appropriato • Il metodo action viene invocato per gestire gli eventi che intressano i controlli fondamentali: trattasi di un livello di astrazione superiore a quello degli elementari (pressioni e rilasci di tasti) • Il valore false ritornato da un gestore di eventi richiede che l'evento venga successivamente passato anche al padre della Component ESEMPIO: OGGETTO PRIVO DI GESTORE SPECIFICO Non esistendo un metodo action per Scrollbar public boolean handleEvent(Event e) { if (e.target instanceof Scrollbar) { ... } return super.handleEvent(e); } Ultima riga: cfr. l'uso di super nei costruttori... LAYOUT MANAGER • Controlla dimensioni e posizionamento delle Component contenute in un Container • Ogni Container contiene un LayoutManager di default (ma ridefinibile dall'utente) • Cinque tipi di LayoutManager predefiniti (BorderLayout, CardLayout, FlowLayout, GridLayout, GridBagLayout) • Altri LayoutManager disponibili sulla rete o programmabili direttamente da utente PRIMITIVE GRAFICHE Metodi principali della classe Graphics • • • • • • • • • drawLine drawRect, fillRect, clearRect draw3DRect, fill3DRect drawRoundRect, fillRoundRect drawOval, fillOval drawArc, fillArc drawPolygon, fillPolygon drawBytes, drawChars, drawString drawImage Non esistono ancora metodi per formati video