Programmazione ad oggetti in Java E Mumolo DEEI

  • Slides: 73
Download presentation
Programmazione ad oggetti in Java E. Mumolo, DEEI mumolo@units. it 1

Programmazione ad oggetti in Java E. Mumolo, DEEI mumolo@units. it 1

Ricapitolando … n OOP è un paradigma di programmazione nel quale i problemi sono

Ricapitolando … n OOP è un paradigma di programmazione nel quale i problemi sono modellati come in insieme di oggetti. Gli oggetti: q q q n n n Comunicano mediante invio di messaggi Hanno un loro stato interno Sono caratterizzati dal loro stato, comportamento e identità Una classe è un insieme di oggetti con gli stessi comportamenti Un oggetto è una istanza di una classe Caratteristiche degli oggetti: q Incapsulamento q Polimorfismo q Ereditarietà q Aggregazione q Identità 2

Ricapitolando … n Livelli di accesso n Privato q n Pubblico q n I

Ricapitolando … n Livelli di accesso n Privato q n Pubblico q n I campi privati possono essere acceduti solo dai campi che fanno parte della classe I campi privati possono essere acceduti da qualunque parte Protetto q Nel caso che la definizione di una classe sia derivata da un’altra classe, tutto ciò che è definito come protetto viene ereditato 3

Ricapitolando … n n n Una classe è un insieme di oggetti con gli

Ricapitolando … n n n Una classe è un insieme di oggetti con gli stessi comportamenti Un oggetto è una istanza di una classe Caratteristiche degli oggetti: q q q n Terminologia: q q q n Incapsulamento Polimorfismo Ereditarietà Aggregazione Identità Classe derivata: classe ottenuta mediante specializzazione di un’altra classe Classe base: la classe dalla quale una classe è derivata Ereditarietà: una classe derivata eredita da una classe base Ereditarietà impropria: quando la classe base ha una capacità che la classe derivata non può soddisfare (esempio: nella derivazione struzzo uccello la classe base ha un metodo vola()) 4

Ricapitolando … n Terminologia: q q q Classe derivata: classe ottenuta mediante specializzazione di

Ricapitolando … n Terminologia: q q q Classe derivata: classe ottenuta mediante specializzazione di un’altra classe Classe base: la classe dalla quale una classe è derivata Ereditarietà: una classe derivata eredita da una classe base n Ereditarietà impropria: quando la classe base ha una capacità che la classe derivata non può soddisfare (esempio: nella derivazione struzzo: uccello la classe base ha un metodo vola()) n Costruttori/distruttori: inizializzazione var-rilascio spazio q q q Istanziazione oggetto/terminazione oggetto nome uguale alla classe, senza return parametri opzionali, possibili costruttori multipli Costruttore di default / di copia Attenzione: l’inizializzazione del costruttore segue l’ordine di definizione variabili 5

Ricapitolando … n Ereditarietà q q n Relazione has-a (composizione) Relazione is-a (specializzazione/derivazione) Esempio:

Ricapitolando … n Ereditarietà q q n Relazione has-a (composizione) Relazione is-a (specializzazione/derivazione) Esempio: q Se il problema si descrive con la frase: …un veicolo contiene una o più ruote… Implementare la classe ‘ruota’ e poi la classe ‘veicolo’: class veicolo{ private: Ruota r 1, r 2, r 3; } q Se si descrive con la frase: …un’auto è un veicolo… Implementare la classe ‘veicolo’ e poi la classe ‘auto’: class auto: public veicolo{ private: . . . } auto a=new auto(); veicolo v=new veicolo(); v=a; //lecito a=v; //errato 6

Ricapitolando … n Polimorfismo: q q q n Capacità degli oggetti di differenti classi

Ricapitolando … n Polimorfismo: q q q n Capacità degli oggetti di differenti classi legate da ereditarietà di rispondere differentemente alla stessa chiamata Ottenuto mediante overloading delle funzioni virtuali Abbinamento statico delle funzioni agli oggetti Statico: legato al tipo del puntatore, non al tipo dell’oggetto puntato ‘casting’ per indicare esplicitamente il tipo del puntatore Funzioni virtuali: q q q Abbinamento dinamico della funzione all’oggetto I costruttori NON possono essere virtuali I distruttori possono invece esserlo: recuperano lo spazio dell’oggetto puntato 7

Polimorfismo e funzioni virtuali n n Polimorfismo: capacità di rispondere in modo differenziato agli

Polimorfismo e funzioni virtuali n n Polimorfismo: capacità di rispondere in modo differenziato agli stessi comandi realizzato con overloading delle funzioni e con le funzioni virtuali overloading delle funzioni: la scelta della funzione da attivare è effettuata esaminando una lista degli operandi o il tipo di oggetti tramite cui vengono operate le richieste alle operazioni n n n abbinamento statico(static binding): deciso alla compilazione abbinamento dinamico(dynamic binding): deciso in runtime overloading quando gli oggetti vengono rappresentati con puntatore: i puntatori possono puntare a oggetti di tipo diverso! ma l'abbinamento statico si basa sul tipo di puntatore e non sul tipo di oggetto puntato! funzione virtuale: funzione il cui abbinamento con l'oggetto è fatto in run-time 8

Polimorfismo e funzioni virtuali n n n Una funzione definita virtuale nella classe base

Polimorfismo e funzioni virtuali n n n Una funzione definita virtuale nella classe base in una gerarchia di derivazione, rende virtuali tutte le funzioni con stesso prototipo e componenti la classe derivata L'abbinamento dinamico oggetto-funzione con le funzioni virtuali funziona solo se gli oggetti sono gestiti con puntatore. Se l'oggetto gestito con il nome, l'associazione e' statica. Tre casi in cui la chiamata di una funzione virtuale è risolta staticamente: n n quando la chiamata e’ effettuata con un oggetto e non con un puntatore quando si usa scope (: : ) alla classe nella chiamata con puntatore quando una funzione virtuale è chiamata all'interno di costruttore o distruttore Costruttori e distruttori virtuali n n Un costruttore non puo’ essere mai dichiarato virtuale (deve essere dichiarato prima) Distruttori possono essere virtuali! 9

Vantaggi del polimorfismo n n n n Permette di scrivere codice generico che si

Vantaggi del polimorfismo n n n n Permette di scrivere codice generico che si adatta automaticamente alle specializzazioni future Permette di creare nuovi metodi senza cambiare il resto del codice Semplice estensione del codice pre-esistente riutilizzabilita’ del codice Attenzione: se l’impostazione e’ corretta, si puo’ cambiare molto lavorando poco… …se si modifica troppo il codice originale, l’impostazione e’ sbagliata! Modifiche concentrate migliore manutenzione Attenzione: i vantaggi si pagano con una certa perdita di efficienza! 10

Cos’è Java n n Linguaggio di programmazione definito dalla Sun Obiettivo: sviluppo di applicazioni

Cos’è Java n n Linguaggio di programmazione definito dalla Sun Obiettivo: sviluppo di applicazioni sicure, efficienti, robuste, su piattaforme multiple, in reti eterogenee e distribuite Linguaggio semplice e orientato agli oggetti Interpretato: produce codice intermedio (“byte-code”) per una “Java Virtual machine”: Codice sorgente n n Byte code Interprete Portabile su diverse piattaforme Architetturalmente neutro: q q n compilatore Byte-code indipendente dalla architettura hardware Il byte-code puo’ eseguire su un sistema che abbia un ambiente run-time Java Robustezza: controlli estesi in compilazione e run-time

Il byte-code Sorgente in Java { int i; int a; a=0; for(i=0; i<5; i++){

Il byte-code Sorgente in Java { int i; int a; a=0; for(i=0; i<5; i++){ } Traduzione in byte-code: a += i; } Method void main(java. lang. String[]) 0 iconst_0 // push costante 0 1 istore_2 // memorizza in var. locale 2 (a) 2 iconst_0 // push costante 0 3 istore_1 // memorizza in var. locale 1 (i) 4 goto 14 // vai alla riga 14 7 iload_2 // prendi a (push) 8 iload_1 // prendi i (push) 9 iadd // a+i 10 istore_2 // a = a+i 11 iinc 1 1 // i=i+1 14 iload_1 // prendi i (push) 15 iconst_5 // push costante 5 16 if_icmplt 7 // salta a 7 se i<5 19 return // esci

Cos’è Java (cont. ) n Distribuito: q q q n Sicurezza: q q q

Cos’è Java (cont. ) n Distribuito: q q q n Sicurezza: q q q n n Pensato per essere eseguito in rete Funzioni di rete di basso e alto livello Rete accessibile come i file locali Alcune caratteristiche del byte-code sono verificate prima della interpretazione salta molti controlli fatti normalmente a run-time efficienza Indirizzamenti controllati dall’interprete Possibilita’ di caricamento dinamico delle classi dalla rete Concorrente (threaded) q q Applicazioni concorrenti piu’ facili da scrivere Migliore interazione

Java e la rete Sorgente Java Carica le classi Compilatore Verifica e interpreta il

Java e la rete Sorgente Java Carica le classi Compilatore Verifica e interpreta il byte-code Byte-code RETE Ambiente di esecuzione Network computing Rete Programmi e dati Calcolatore in rete (non solo dati)

Java White Paper (Sun, 1995) n Primo scopo: eliminare la ridondanza del C e

Java White Paper (Sun, 1995) n Primo scopo: eliminare la ridondanza del C e C++: q q n n Principi guida di un buon linguaggio: semplicita’, unicita’, consistenza Unicita’: fornire un buon modo per esprimere ogni operazione che interessa, evitare che ce ne siano due Altri linguaggi OO: Eiffel, Smalltalk, Ada Applicazioni o Applets? q q n Caratteristiche sovrapposte, troppi modi per fare la stessa cosa C++ aggiungendo classi a C, aumenta la ridondanza Applet: codice creato per far parte di un documento Applicazioni: compilatore scaricabile da rete (esempio, ftp. sun. com/pub) Alcuni strumenti Java: q q q javac <file. java> compila la classe in byte code java <nome_della_classe_main> java virtual machine: interpreta byte code appletviewer <url|file> visualizza un applet jdb <file[. class]> java debugger javap <file[. class]> reverse eng. , disassembla etc. jar Java Archive: jar cf jar-file input-file(s)

#include <stdio. h> // semplice esempio di programmazione C++ bubble sort #include <iostream. h>

#include <stdio. h> // semplice esempio di programmazione C++ bubble sort #include <iostream. h> #include <stdlib. h> #include <string. h> struct sistema { float *aa; const int ord=10, ord 1=3; int ord; }; // variabili non modificabili! int bubble(float *, int N=ord); void scambia(float &, float &); // passaggio per riferimento void stampa(int); void stampa(float *a, int n=ord); main() { sistema SS[ord 1]; // definisce l'array SS di ord 1 strutture 'sistema' int nl; for(short i=0; i<ord 1; i++){ //carica le strutture cout<<endl<<"carica"<<i; SS[i]. ord=5+random(10); float[SS[i]. ord]; //alloca l'array in memoria libera SS[i]. aa = new for(short j=0; j<SS[i]. ord; j++) {SS[i]. aa[j]=float(random(100)); cout<<SS[i]. aa[j]<<" "; } } for(short i=0; i<ord 1; i++){ printf("nn. Array originale %d: n", i); nl=bubble(SS[i]. aa, SS[i]. ord); } } stampa(SS[i]. aa, SS[i]. ord); //argomento di default stampa(nl); //overloading di funzioni e valori default stampa(SS[i]. aa, SS[i]. ord); //overloading di funzioni e valori default

int bubble(float *A, int N) { char *flag="notsorted"; int nloop=0; while(!strcmp(flag, "notsorted")){ flag="sorted"; nloop++;

int bubble(float *A, int N) { char *flag="notsorted"; int nloop=0; while(!strcmp(flag, "notsorted")){ flag="sorted"; nloop++; for(short i=0; i<N-1; i++) if(*(A+i) > *(A+i+1)){ //A[i] e' *(A+i) scambia(*(A+i), *(A+i+1)); //passa per riferimento!! flag="notsorted"; } } return nloop; } void scambia(float &a, float &b) { float temp=a; a=b; b=temp; // il compilatore passa l'indirizzo delle var. } void stampa(int n) { printf("n. Array ordinato (nr. cicli=%d): n", n); } void stampa(float *a, int n) { for(short j=0; j<n; j++) } cout << a[j] << " "; cout ; // definizione short

#include <stdio. h> //stesso esempio di programmazione C++ rimuovendo i puntatori espliciti #include <iostream.

#include <stdio. h> //stesso esempio di programmazione C++ rimuovendo i puntatori espliciti #include <iostream. h> #include <stdlib. h> #include <string. h> struct sistema { float *aa; const int ord=10, ord 1=3; int ord; }; // variabili non modificabili! int bubble(float *, int N=ord); //argomento di default void scambia(float *, int); // passaggio per riferimento void stampa(int); void stampa(float *a, int n=ord); main() { sistema SS[ord 1]; // definisce l'array SS di ord 1 strutture 'sistema' int nl; for(short i=0; i<ord 1; i++){ //carica le strutture cout<<endl<<"carica"<<i; SS[i]. ord=5+random(10); //alloca l'array nella memoria libera SS[i]. aa = new float[SS[i]. ord]; for(short j=0; j<SS[i]. ord; j++) {SS[i]. aa[j]=float(random(100)); cout<<SS[i]. aa[j]<<" "; } } for(short i=0; i<ord 1; i++){ printf("nn. Array originale %d: n", i); stampa(SS[i]. aa, SS[i]. ord); nl=bubble(SS[i]. aa, SS[i]. ord); //argomento di default } } stampa(nl); //overloading di funzioni e valori default stampa(SS[i]. aa, SS[i]. ord); //overloading di funzioni e valori default

int bubble(float A[], int N) { char *flag="notsorted"; int nloop=0; while(!strcmp(flag, "notsorted")){ flag="sorted"; nloop++;

int bubble(float A[], int N) { char *flag="notsorted"; int nloop=0; while(!strcmp(flag, "notsorted")){ flag="sorted"; nloop++; for(short i=0; i<N-1; i++) if(A[i] > A[i+1]){ scambia(A, i); flag="notsorted"; } } return nloop; } void scambia(float a[], int i) { float temp=a[i]; // il compilatore passa l'indirizzo delle var. a[i]=a[i+1]; a[i+1]=temp; } void stampa(int n) { printf("n. Array ordinato (nr. cicli=%d): n", n); } void stampa(float *a, int n) { for(short j=0; j<n; j++) cout << a[j] << " "; cout ; // definizione short }

//stesso programma, sort, scritto in java import java. io. *; import java. util. Random;

//stesso programma, sort, scritto in java import java. io. *; import java. util. Random; class sort{ static int bubble(float A[], int N) { String flag="notsorted"; int nloop=0; while(flag!="sorted"){ flag="sorted"; nloop++; for(short i=0; i<N-1; i++) if(A[i] > A[i+1]){ scambia(A, i); flag="notsorted"; } } return nloop; } static void scambia(float a[], int i) { float temp=a[i]; a[i]=a[i+1]; a[i+1]=temp; }

static void stampa(int n) { System. out. print("Array ordinato (nr. cicli=" + n +")");

static void stampa(int n) { System. out. print("Array ordinato (nr. cicli=" + n +")"); System. out. println(); } static void stampa(float a[], int n) { for(short j=0; j<n; j++) System. out. print(a[j] + " "); System. out. println(); } public static void main(String argv[]) { int ord 1=2; int nl; int ord[] = new int[ord 1]; float SS[][] = new float[ord 1][20]; Random r = new Random(); for(short i=0; i<ord 1; i++){ System. out. println(); //carica le strutture System. out. print("carica " + i +": "); ord[i]=1+(int)(r. next. Float()*10); for(short j=0; j<ord[i]; j++) {SS[i][j]=(int)(r. next. Float()*100); System. out. print(SS[i][j] + " "); } } for(short i=0; i<ord 1; i++){ System. out. print("n. Array originale " + i +"= "); System. out. println(); stampa(SS[i], ord[i]); nl=bubble(SS[i], ord[i]); } } } // fine del main //fine della classe stampa(nl); stampa(SS[i], ord[i]);

Osservazioni n n n Per gran parte e’ codice C++ Non ci sono variabili

Osservazioni n n n Per gran parte e’ codice C++ Non ci sono variabili globali Case sensitive Un programma java e’ sempre un insieme di classi: nel programma, la classe e’sort i cui metodi sono bubble, scambia, stampa, main Il main e’ chiamato differentemente dal C++: C++ void main(int argc, char * argv[]) Esempio: prog 5 argc=2, argv[0]=“prog”, argv[1]=5 n n Java public static main(String argv[]) argv[0]=5, argv. lenght=1 L’input/optput e’ diverso dal C++: System. out(xx) = cout << xx #include e’ sostituito da import: java. util. random e’ la classe Random dal package util Cosi’, Random r=new Random() crea una istanza della classe Random e r. next. Float() genera un numero random tra 0 e 1 attivando il metodo next. Float Assenza di struct e union in Java: in C++ e’ una parte dipendente dalla macchina (allineamenti e dimensioni)

Costanti, variabili, identificatori n n Non esiste ne’ #define ne’ const Definizione di una

Costanti, variabili, identificatori n n Non esiste ne’ #define ne’ const Definizione di una costante: final n n nome_costante = valore; Definizione di una variabile: tipo_variabile nome_variabile [=valore][, nome_variabile [=valore]…] Convenzioni per i nomi identificatori: q q q n tipo_costante Case misto per i nomi delle classi (es. : Mia. Classe) I nomi delle costanti sono in lettere capitali (es. : PI_GRECO) Altri nomi (funzioni, variabili, parole riservate) sono in minuscolo o con case misto, partendo pero’ con una lettera minuscola Visibilita’ delle variabili: all’interno di un blocco { }. Se i blocchi sono annidati, non e’ possibile usare lo stesso nome

Tipi di dati n n Tipi semplici: Interi, virgola mobile, caratteri, logici Interi: tutti

Tipi di dati n n Tipi semplici: Interi, virgola mobile, caratteri, logici Interi: tutti con segno (non esiste l’unsigned) q q n q 32 bit 64 bit Char 16 bit senza segno, codifica Unicode Logici: q n Float Double Caratteri: q n 8 bit con segno 16 bit con segno, big endian, high byte first 32 bit con segno 64 bit con segno Virgola mobile: formato IEEE-754 q n Byte Short Int Long Boolean due valori possibili, true e false Casting fra tipi primitivi, promozione automatica

Casting n Casting di tipi primitivi: q Perdita di precisione q Boolean non puo’

Casting n Casting di tipi primitivi: q Perdita di precisione q Boolean non puo’ essere convertito in nessun tipo primitivo n Casting di oggetti: q q n La classe di partenza e di arrivo devono essere in relazione ereditaria Casting in superclasse fa’ perdere i dati della sottoclasse Casting tra tipi primitivi e oggetti: q Il package java. lang comprende classi speciali: Integer, Float, Boolean, … per rappresentare oggetti equivalenti ai tipi primitivi Integer o = new Iteger(22); q // tratta un valore come un oggetto Casting tra oggetti a dati primitivi: mediante metodi speciali Int n = o. int. Value(); //restituisce 22

Array • • Array o matrici: sono oggetti! Una variabile array punta a tutto

Array • • Array o matrici: sono oggetti! Una variabile array punta a tutto l’oggetto. Campo dell’oggetto: length Array monodimensionali: • int buf[]; esempio di dichiarazione di array di interi • buf = new int[10]; esempio di allocazione • String nome[]; esempio di dichiarazione di stringa class buffer{ public static void main(String args[]) { int buf[] = new int[10]; //buf e’ un puntatore ad un oggetto array float arr[] = new float[10]; buf[0]=1; int buf[] = new int[5]; // il vecchio array e’ eliminato (garbage) arr[5] = 3. 14; float[] new; //altro modo per dichiarare un array new=arr; //arr e new puntano allo stesso oggetto array System. out. println(“Valore di buf[0] = “ + buf[0]+”nr. elementi “+buf. length); } } • Array multidimensionali: • int buf[][] = new int[10][5]; //esempio di matrice di interi

Array (cont. ) • • I componenti di un array; • Sono tutti dello

Array (cont. ) • • I componenti di un array; • Sono tutti dello stesso tipo • Possono essere di tipo primitivo o riferimenti • Sono indicizzati con int (controllo a run-time) Dichiarazione: int[] a; oppure int a[]; • Creazione: a=new int[3]; • Uso: a[0]=1; • Array di array: int a[][]; a=new int[3][2]; • Array di oggetti: class B{…} Spazio dati: a null Spazio heap: a B a[]; 1 a a=new B[3];

Packages n n n Definizione di classi: simile a C++. Esistono classi predefinite, raggruppate

Packages n n n Definizione di classi: simile a C++. Esistono classi predefinite, raggruppate in packages Ogni classe va’ in un file separato: il nome del file sorgente deve essere esattamente uguale al nome della classe, con estensione “. java” La import (es. import java. io. *) importa tutte le classi di un package Ogni programma inizia con import java. lang. *; (inserimento predefinito) La import puo’ essere omessa, indicando esplicitamente quale classe si vuole utilizzare esempio: import java. util. Random; Random r = new Random(); oppure: java. util. Random r; r = new java. util. Random();

Packages n n Attenzione: la import non importa nulla. E’ solo una abbreviazione! Il

Packages n n Attenzione: la import non importa nulla. E’ solo una abbreviazione! Il compilatore javac importa la classe quando richiesta, eventualmente compilando il file. java. class Messaggi { void msg 1(){ System. out. println(“Primo messaggio”); void msg 2(){System. out. println(“Secondo messaggio”); } class Test { public static void main(String[] args){ Messaggi m 1 = new Messaggi; Messaggi m 2 = new Messaggi; m 1. msg 1(); m 2. msg 2() } n Le due classi vanno in due file, chiamati Messaggi. java e Test. java. Basta scrivere: javac test. java 29

Puntatori n n n Gli oggetti in Java possono solo essere acceduti tramite puntatori

Puntatori n n n Gli oggetti in Java possono solo essere acceduti tramite puntatori Una variabile puo’ contenere valori primitivi o riferimento a oggetti Una variabile non puo’ contenere un oggetto Non esistono gli operatori “*”, “&”, “->” ma solo l’operatore punto “. ” I membri della classe sono per default friend di altre classi del package 30

Puntatori Esempio C++ #include <iostream. h> #include <math. h> class punto { friend class

Puntatori Esempio C++ #include <iostream. h> #include <math. h> class punto { friend class stampa; float x, y; //private public: punto(float a, float b){x=a; y=b; }; float distanza(punto *a){ float t=pow(x-a->x, 2)+pow(y-a->y, 2); return sqrt(t); } }; class stampa{ public: void out(float a, float b, float c, float d) { punto *p, *q=new punto(a, b), *r; cout << q->x << " " << q->y << endl; p->x=c; p->y=d; cout << p->x << " " << p->y << endl; cout << q->distanza(p); } }; main() { stampa s; s. out(1, 2, 5, 5); } Esempio Java class punto { //file punto. java float x, y; punto(float a, float b){x=a; y=b; }; float distanza(punto a){ float t=(float)(Math. pow(x-a. x, 2)+Math. pow(y-a. y, 2)); return (float)Math. sqrt(t); } }; import java. io. *; class dots{ //file dots. java static void out(float a, float b, float c, float d) { punto p=new punto(0, 0), q=new punto(a, b), r; System. out. println(q. x +" "+ q. y); p. x=c; p. y=d; } } System. out. println(p. x + " " + p. y); System. out. println("distanza="+ q. distanza(p)); public static void main(String argv[]) { out(1, 2, 5, 5); System. exit(0); }

Garbage collection n n Come in C++, un oggetto e’ creato con new Delete

Garbage collection n n Come in C++, un oggetto e’ creato con new Delete in C++ puo’ introdurre errori: cancellazione prematura, cancellazione tardiva In Java non esiste l’operatore delete Cancellazione automatica di oggetti quando non ci sono piu’ riferimenti ad essi

Incapsulamento n n Membri privati: accesso consentito solo dall’interno dei metodi della classe Membri

Incapsulamento n n Membri privati: accesso consentito solo dall’interno dei metodi della classe Membri protetti: accesso consentito alla classe e alle classi derivate Membri pubblici: accesso consentitoa qualsiasi funzione Sintassi C++ Sintassi Java class Mia{ Private: private int i; double d; public private Public: int j; void funzione() { … } int i; int j; double d; public void funzione() {…} } } n n Di default, i membri sono visibili pubblicamente Membri statici: esiste solo una copia condivisa da tutte le instanze

//file Veicolo. java class Veicolo { private int Velocita. Massima; private int Numero. Posti;

//file Veicolo. java class Veicolo { private int Velocita. Massima; private int Numero. Posti; public Veicolo(int VM, int NP) // costruttore { Velocita. Massima = VM; Numero. Posti = NP; } } //file mioveicolo. java public class mioveicolo { public static void main(String args[]) { Veicolo Mia. Macchina= new Veicolo(150, 5); System. out. println("Creato un oggetto di classe Veicolo"); } }

//file Veicolo. java class Veicolo { private int Velocita. Massima; // variabili private int

//file Veicolo. java class Veicolo { private int Velocita. Massima; // variabili private int Numero. Posti; // semantica per valore public Veicolo(int VM, int NP) // costruttore { Velocita. Massima = VM; Numero. Posti = NP; } public int get. Velocita. Max() // metodi pubblici { return Velocita. Massima; } public int get. Numero. Posti() { return Numero. Posti; } } //file mioveicolo 2. java public class mioveicolo 2 { public static void main(String args[]) { int Intero; Veicolo Mia. Macchina = new Veicolo(150, 5); System. out. print("La mia macchina ha "); System. out. print(Mia. Macchina. get. Numero. Posti()+" posti"); System. out. print(" e raggiunge la velocita' di "); System. out. println(Mia. Macchina. get. Velocita. Max() + " km/h. "); // Intero = Mia. Macchina. Numero. Posti; // il compilatore da' errore } }

Stringhe n n Il tipo String crea un array di char L’operatore + e’

Stringhe n n Il tipo String crea un array di char L’operatore + e’ sovrapposto per introdurre la concatenazione La concatenazione puoì essere fatta con qualsiasi cosa: conversione automatica in stringa Operazioni piu’ comuni (String s=“blabla”) q q q s. char. At(n) s s. substring(n) fine s. compare. To(str) “str” s. index. Of(‘c’) s. last. Index. Of(‘c’) s. ends. With(“str”) ritorna il carattere alla posizione n della stringa ritorna la sottostringa di s dalla posizione n alla <, >, == 0 se “s” precede, segue, e’ uguale a ritorna il primo indice del carattere ‘c’ in “s” ritorna l’ultimo indice del carattere ‘c’ in “s” ritorna vero o falso

Costruttori e sovrapposizione n n I costruttori in Java hanno lo stesso significato del

Costruttori e sovrapposizione n n I costruttori in Java hanno lo stesso significato del C++ Differenza: () anche se non ho argomenti Differenza: i costruttori devono essere scritti in linea Sovrapposizione (overloading): piu’ costruttori, con diversi argomenti class punto { //file punto. java float x, y; punto(float a, float b){ x=a; y=b; //stesso che this. x=a; this. y=b; }; punto(float a){ x=a; y=0; }; punto(){ x=0; y=0; }; import java. io. *; class dots{ //file dots. java public static void main(String argv[]) { punto p 1=new punto(1, 2); punto p 2=new punto; //errore punto p 3=new punto(); System. exit(0); } }

Ereditarieta’ n Due tipi di ereditarieta’: di metodo e di interfaccia n Ereditarieta’ di

Ereditarieta’ n Due tipi di ereditarieta’: di metodo e di interfaccia n Ereditarieta’ di metodo: q eredità singola, parola chiave: extends q L’istruzione super fa’ riferimento alla classe del padre) q La classe figlia eredita: q n variabili e metodi della classe padre definiti public n variabili e metodi della classe padre definiti protected n variabili e metodi della classe padre senza attributo se appartiene allo stesso package n variabili e metodi che la classe padre ha ereditato dagli «avi» della gerarchia Riutilizzare componenti già definiti, specializzandoli class Base{ // superclasse void fz 1(){…} void fz 2(){…} }; Class Derivata extends Base{ void fz 2(){…} //sostituisce fx 2() di Base (overriding) void fz 3(){ super. fz 2(); //la classe Derivata ha tre metodi, fz 1, fz 2, f 3 //si riferisce al padre! . . . } }; n Ereditarieta’ di interfaccia q //sottoclasse di Base eredità multipla, parola chiave: implements

//file Veicolo. java class Veicolo //uguale a quello precedente! { … } //file Veicolo.

//file Veicolo. java class Veicolo //uguale a quello precedente! { … } //file Veicolo. Terrestre. java class Veicolo. Terrestre extends Veicolo { private int Numero. Ruote; public Veicolo. Terrestre(int VM, int NP, int NR) // costruttore { super(VM, NP); // chiama il costruttore del padre Numero. Ruote = NR; } public int get. Numero. Ruote() { return Numero. Ruote; } } //file Veicolo. Marino. java class Veicolo. Marino extends Veicolo { private long Stazza; public Veicolo. Marino(int VM, int NP, long S) { super(VM, NP); Stazza = S; } public long get. Stazza() { return Stazza; } } //file mioveicolo 3. java public class mioveicolo 3 { public static void main(String args[]) { Veicolo. Terrestre Mia. Macchina = new Veicolo. Terrestre(100, 5, 4); Veicolo. Marino Mia. Navenew Veicolo. Marino(5, 10); System. out. print("La mia macchina ha "); System. out. print(Mia. Macchina. get. Numero. Posti() + " posti, "); System. out. println(Mia. Macchina. get. Numero. Ruote() + " ruote"); System. out. println(" e una velocita' di "+Mia. Macchina. get. Velocita. Max()+"KM/h" System. out. print("La mia nave ha "); System. out. print(Mia. Nave. get. Numero. Posti() + " posti, "); System. out. println("una stazza di " + Mia. Nave. get. Stazza()); System. out. println(" e una velocita' di "+Mia. Nave. get. Velocita. Max()+"nodi/h"); } }

Interfacce n n Interfaccia: struttura sintattica con nome Specifica i nomi, gli argomenti e

Interfacce n n Interfaccia: struttura sintattica con nome Specifica i nomi, gli argomenti e i tipi di ritorno dei metodi di una classe non interface Punto { ancora implementata } n punto(float a, float b); float distanza(punto a); Una interfaccia puo’ essere implementata da una o piu’ classi class Mio. Punto implements Punto { float x, y; punto(float a, float b) ){x=a; y=b; }; float distanza(punto a) { float t=(float)(Math. pow(x-a. x, 2)+Math. pow(y-a. y, 2)); return (float)Math. sqrt(t); }; class Tuo. Punto implements Punto { float x, y; punto(float a, float b) ){x=2*a; y=2*b; }; float distanza(punto a) { float t=(float)(Math. abs(x-a. x)+Math. abs(y-a. y)); return (float)Math. sqrt(t)} }; n Una classe puo’ implementare piu’ di una interfaccia ereditarieta’ multipla class Mia. Classe implements A, B{…}

Costruttori e sovrapposizione n n I costruttori in Java hanno lo stesso significato del

Costruttori e sovrapposizione n n I costruttori in Java hanno lo stesso significato del C++ Differenza: () anche se non ho argomenti Differenza: i costruttori devono essere scritti in linea Sovrapposizione (overloading): piu’ costruttori, con diversi argomenti class punto { //file punto. java float x, y; punto(float a, float b){ x=a; y=b; //stesso che this. x=a; this. y=b; }; punto(float a){ x=a; y=0; }; punto(){ x=0; y=0; }; }; import java. io. *; class dots{ //file dots. java public static void main(String argv[]) { punto p 1=new punto(1, 2); punto p 2=new punto; //errore punto p 3=new punto(); System. exit(0); } }

Eccezioni n n n n Java non crea core files Errori di run-time fanno

Eccezioni n n n n Java non crea core files Errori di run-time fanno scattare una eccezione Di default, una eccezione causa la terminazione di un programma Le eccezioni possono essere catturate con le istruzioni catch-try try{. . . //istruzioni, chiamate a funzioni etc. da osservare } catch(Tipo. Di. Eccezione e){ //cattura l’eccezione. . . //descrive cosa fare quando } Eccezioni built-in: Arithmetic. Exception, Null. Pointer. Exception, Class. Cast. Exception, IOException, Array. Index. Out. Of. Bounds. Exception, Negative. Array. Size. Exception, Out. Of. Memory. Exception, … Una eccezione e’ un oggetto, che viene ereditato da altri oggetti L’istruzione catch cattura una eccezione e le sue derivate Le eccezioni possono essere definite dall’utente con throw (lancia eccezioni) q Definizione della classe Nuova. Eccezione q throw new Nuova. Eccezione(); q try {…} catch (Nuova. Eccezione e) { …}

Il tipo “Vector” n n n Un Vector e’ un array dinamico Gli elementi

Il tipo “Vector” n n n Un Vector e’ un array dinamico Gli elementi di un Vectorsono oggetti, non valori La classe Vector e’ realizzata come un array ordinario import java. util. *; import java. io. *; class vect{ public static void main(String argv[]) { int n; Integer o; Vector v=new Vector(); System. out. println("carico il Vector di interi"); for(int i=0; i<10; i++) v. add. Element(new Integer(i*2)); System. out. println("visualizzo Vector: "); for(int i=0; i<10; i++) { o=(Integer) v. element. At(i); n=(int)o. int. Value(); System. out. println("elemento "+i+"="+n); } System. exit(0); } }

Costruzione di liste public class List. Node { public Object element ; public List.

Costruzione di liste public class List. Node { public Object element ; public List. Node next ; /** Costruttore nodo isolato */ public List. Node ( Object element ) { this( element, null ) ; } /** Costruttore nodo per liste unidirezionali, dove element e' non public List. Node ( Object element, List. Node next ) { if ( element == null ) throw new Illegal. Argument. Exception ( ) ; } } this. element = element ; this. next = next ; null */

Polimorfismo n n Gli oggetti della classe derivata hanno la stessa interfaccia della classe

Polimorfismo n n Gli oggetti della classe derivata hanno la stessa interfaccia della classe base, o un suo sovrainsieme Gli oggetti della classe derivata possono essere visti come oggetti ‘estesi’ della classe base Variabili del tipo della classe base possono contenere riferimenti a oggetti della classe derivata Quando viene inviato un messaggio a un oggetto, la scelta dell’implementazione del metodo è effettuata dinamicamente sulla base della classe effettiva, non del tipo della variabile (polimorfismo)

//file Animale. java public class Animale { public void verso() { System. out. println("Che

//file Animale. java public class Animale { public void verso() { System. out. println("Che animale sono? "); } } //file Cane. java public class Cane extends Animale { public void verso() { System. out. println("Sono un cane: Bau bau!"); } } //file Gatto. java public class Gatto extends Animale { public void verso() { System. out. println("Sono un gatto: Miao!"); } } //file Versi. Animali. java public class Versi. Animali { public static void main(String args[]) { } } Animale t; Animale a=new Animale(); t=a; t. verso(); t=b; t. verso(); t=c; t. verso(); Animale b=new Cane(); Animale c=new Gatto();

//file Poli. Veicolo. java class Poli. Veicolo { private int Velocita. Massima; private int

//file Poli. Veicolo. java class Poli. Veicolo { private int Velocita. Massima; private int Numero. Posti; public Poli. Veicolo(int VM, int NP) { Velocita. Massima = VM; Numero. Posti = NP; } public int get. Velocita. Max() { return Velocita. Massima; } public int get. Numero. Posti() { return Numero. Posti; } public String stampa() {return "Veicolo con "+Numero. Posti+"posti e velocita' massima di“ +Velocita. Massima+"km/h"; }; } //file Ferrari. java class Ferrari extends Poli. Veicolo { public Ferrari(int VM, int NP) // costruttore { super(VM, NP); } public String stampa() //ridefinisce il metodo { return "Sono una Ferrai, ho " + get. Numero. Posti() + " posti"+ "e vado a” + get. Velocita. Max()+"Km/h"; } } //file Fiat 500. java class Fiat 500 extends Poli. Veicolo { public Fiat 500(int VM, int NP) // costruttore { super(VM, NP); } public String stampa() //ridefinisce il metodo { return "Sono una Fiat 500, ho " + get. Numero. Posti() + " posti" + "e posso andare a”+ get. Velocita. Max()+"Km/h"; } } //file Veicoli. java public class Veicoli { public static void main(String args[]) { Poli. Veicolo v=new Poli. Veicolo(0, 0); // istanza della classe padre Ferrari v 1 = new Ferrari(300, 1); Fiat 500 v 2 = new Fiat 500(100, 4); System. out. println(v. stampa()); v = v 1; System. out. println(v. stampa()); v = v 2; System. out. println(v. stampa()); } }

Input/output in Java n n Flusso di dati sorgente-destinazione Potenza della astrazione: sorgente/destinazione possono

Input/output in Java n n Flusso di dati sorgente-destinazione Potenza della astrazione: sorgente/destinazione possono essere qualsiasi (file, socket, tastiera, monitor etc) In Java si legge e si scrive su un oggetto Stream Classi del package java. io: q q q n n Metodi di lettura: specificano come argomento la sorgente Metodi di lettura: specificano come argomento la destinazione Metodi di elaborazione: leggono i dati dal flusso indicato nel 1 o argomento e scrivono i dati elaborati sul 2 o argomento I metodi di elaborazione non conoscono la sorgente o la distinazione: dettagli nascosti Gerarchia di classi: q q q Reader: input caratteri Writer: output caratteri Input. Stream: input byte Output. Stream: output byte Buffered: associano un buffer allo stream di I-O. Il buffer: n n Permette di trasferire piu’ di un byte alla volta Permette di inserire metodi di skip, mark e reset

Input/output in Java n Legge dallo standard input e scrive sullo standard output import

Input/output in Java n Legge dallo standard input e scrive sullo standard output import java. io. *; //in questo caso considero le eccezioni public class Copia 1 { public static void main(String[] args) { Buffered. Reader in = new Buffered. Reader(new Input. Stream. Reader(System. in)); for(; ; ){ try{ String line=in. read. Line(); System. out. println(line); } catch(IOException e){ System. out. println("errore di IO : " + e); } } n Legge dallo standard input e scrive sullo standard output import java. io. *; // in questo caso trascuro le eccezioni public class Copia { public static void main(String[] args) throws IOException { Buffered. Reader in = new Buffered. Reader(new Input. Stream. Reader(System. in)); for(; ; ){ String line=in. read. Line(); System. out. println(line); } } }

Input/output in Java Copia il file README nel file READout per interi n import

Input/output in Java Copia il file README nel file READout per interi n import java. io. *; public class prova { public static void main(String[] args) throws IOException { File. Input. Stream f = new File. Input. Stream("README"); File. Output. Stream f 1 = new File. Output. Stream("READout"); while(f. available()!=0){ int line=f. read(); f 1. write(line); } } }

Input/output in Java n La classe FILE: descrive le proprieta’ del file. Alcuni metodi

Input/output in Java n La classe FILE: descrive le proprieta’ del file. Alcuni metodi compresi: public java. lang. String get. Name(); public java. lang. String get. Path(); public java. lang. String get. Absolute. Path(); public java. lang. String get. Canonical. Path(); public java. lang. String get. Parent(); public boolean exists(); public boolean can. Write(); public boolean can. Read(); public boolean is. File(); public boolean is. Directory(); public long last. Modified(); public long length(); public boolean mkdir(); public boolean rename. To(java. io. File); public boolean mkdirs(); public java. lang. String list()[]; public boolean delete();

Input/output in Java n Esempio: lista di alcune caratteristiche del file README import java.

Input/output in Java n Esempio: lista di alcune caratteristiche del file README import java. io. *; public class prova 1 { public static void main(String[] args) throws IOException { File f = new File("README"); System. out. println("Nome: " + f. get. Name()); System. out. println("Path: " + f. get. Path()); System. out. println("Dimensione: " + f. length()); } }

Multithreading in Java n n n Ogni thread e’ un oggetto, creato come istanza

Multithreading in Java n n n Ogni thread e’ un oggetto, creato come istanza della classe java. lang. Thread La classe Thread contiene tutti i metodi per gestire i threads L’utente implementa il metodo run() Uno dei metodi piu’ importanti e’ il metodo start() che lancia il thread utilizzando il metodo run definito dall’utente Ogni istanza di Thread deve quindi essere associata ad un metodo run Ci sono due metodi per realizzare un thread: q q n Un thread termina quando q q q n n Implementando l’interfaccia Runnable Estendendo la classe java. lang. Thread e sovrascrivendo il metodo run() Finisce Viene eseguito il metodo stop() del thread Scatta una eccezione Lo scheduling e’ effettuato tramite le priorita’ (metodo set. Priority()) A parita’ di priorita’ round-robin

Multithreading in Java-metodo 1 -prima versione import java. io. *; public class Ping. Pong{

Multithreading in Java-metodo 1 -prima versione import java. io. *; public class Ping. Pong{ //il main crea e lancia i thread public static void main(String[] a){ Ping c=new Ping(); Pong t=new Pong(); Thread th 1=new Thread(c); th 1. start(); Thread th 2=new Thread(t); th 2. start(); } } class Ping implements Runnable{ public void run(){ while(true) { try{ Thread. sleep(800); } catch(Interrupted. Exception e) {} System. out. println("Ping"); } } } class Pong implements Runnable{ public void run(){ while(true) { try{ Thread. sleep(990); } catch (Interrupted. Exception e){} System. out. println("t. Pong"); } } }

Multithreading in Java-metodo 1 -seconda versione import java. io. *; public class Ping. Pong

Multithreading in Java-metodo 1 -seconda versione import java. io. *; public class Ping. Pong 1{ // file Ping. Pong 1. java public static void main(String[] a){ Ping 1 c=new Ping 1(); Pong 1 t=new Pong 1(); } } class Ping 1 implements Runnable{ //file Ping 1. java. Ogni oggetto crea e lancia il proprio thread Thread th; public void run(){ while(true) { try{ Thread. sleep(800); } catch(Interrupted. Exception e) {} System. out. println("Ping"); } } Ping 1() {th=new Thread(this); th. start(); } } class Pong 1 implements Runnable{ //file Pong 1. java Thread th; public void run(){ while(true) { try{ Thread. sleep(990); } catch (Interrupted. Exception e){} System. out. println("t. Pong"); } } Pong 1(){ th=new Thread(this); th. start(); } }

Multithreading in Java-metodo 2 -prima versione import java. io. *; public class Ping. Pong

Multithreading in Java-metodo 2 -prima versione import java. io. *; public class Ping. Pong 2{ // il main crea e lancia i thread public static void main(String[] a){ Ping 2 c=new Ping 2(); c. start(); Pong 2 t=new Pong 2(); t. start(); } } class Ping 2 extends Thread{ public void run(){ while(true) { try{ Thread. sleep(800); } catch(Interrupted. Exception e) {} System. out. println("Ping"); } } } class Pong 2 extends Thread{ public void run(){ while(true) { try{ Thread. sleep(990); } catch (Interrupted. Exception e){} System. out. println("t. Pong"); } } }

Multithreading in Java-metodo 2 -seconda versione import java. io. *; public class Ping. Pong

Multithreading in Java-metodo 2 -seconda versione import java. io. *; public class Ping. Pong 3{ public static void main(String[] a){ Ping 3 c=new Ping 3(); Pong 3 t=new Pong 3(); } } class Ping 3 extends Thread{ //ogni thread si lancia da solo public void run(){ while(true) { try{ Thread. sleep(800); } catch(Interrupted. Exception e) {} System. out. println("Ping"); } } Ping 3(){ start(); } } class Pong 3 extends Thread{ public void run(){ while(true) { try{ Thread. sleep(990); } catch (Interrupted. Exception e){} System. out. println("t. Pong"); } } Pong 3(){ start(); } }

In ogni caso, l’uscita è: C: jdk 1. 1. 8prove>java Ping. Pong 2 Ping

In ogni caso, l’uscita è: C: jdk 1. 1. 8prove>java Ping. Pong 2 Ping Pong Ping Pong Ping. . .

Alcuni metodi di Thread n public void start() //lancia il thread n public void

Alcuni metodi di Thread n public void start() //lancia il thread n public void run() //esegue il codice n public final void stop() //distrugge il thread n public final void suspend() //sospende il thread n public final void resume() //riattiva il thread n public static void sleep(long n) //sospende il thread per n ms n public final void set. Priority(int priority) n public final int get. Priority() //ottiene la priorità corrente n public static void yield() //rischedula n public final native boolean is. Alive() n … //modifica la //priorita’ //esce con true se il //thread è vivo

Stati di un Thread yield() new Thread() New thread suspend() sleep() wait() start() Runnable

Stati di un Thread yield() new Thread() New thread suspend() sleep() wait() start() Runnable stop() run() exit Dead resume() notify() stop() Not Runnable

Passaggio di parametri tra Thread • • Tutti i thread devono condividere un oggetto,

Passaggio di parametri tra Thread • • Tutti i thread devono condividere un oggetto, che contiene i dati e i metodi La condivisione viene effettuata mediante definizione del puntatore all’oggetto in ciascun thread, e mediante l’inizializzazione del puntatore all’oggetto L’oggetto in realta’ viene allocato nella classe principale (quella che contiene il main) Esempio: due thread – pi e po – che si scambiano 5 reali, con ritardo (genera sequenaialita’ quindi in questo caso non ci sono problemi di mutua esclusione) public class pth{ public static void main(String[] a){ z buf=new z(); pi c=new pi(buf); po t=new po(buf); c. start(); t. start(); } } • Definizione della classe z: import java. io. *; public class z{ float b[]= new float[10]; void put(int i, float f){ b[i]=f; float get(int i){ return(float)b[i]; } }

Passaggio di parametri tra Thread • Scrittura delle classi pi. java e po. java

Passaggio di parametri tra Thread • Scrittura delle classi pi. java e po. java public class pi extends Thread{ z buf; pi(z buf){ this. buf=buf; } public void run(){ while(true) { try{ Thread. sleep(800); } catch(Interrupted. Exception e) {} System. out. print("leggo "); for (int i=0; i<5; i++) System. out. print(“ "+buf. get(i)); System. out. println(); } } } class po extends Thread{ z buf; Random r=new Random(); po(z buf){ this. buf=buf; } public void run(){ while(true) { try{ Thread. sleep(990); } catch (Interrupted. Exception e){} System. out. print("tscrivo "); for(int i=0; i<5; i++) { buf. put(i, r. next. Float()); System. out. print(" "+buf. get(i)); } System. out. println(); } } }

Passaggio di parametri tra Thread • In questo esempio si usano dei thread in

Passaggio di parametri tra Thread • In questo esempio si usano dei thread in Java che si scambiano dei dati mediante una classe condivisa, Buffer. La sincronizzazione e’ realizzata mediante algoritmo che attende se i puntatori di in e out sono coincidente. Attenzione: questa soluzione funziona solo con 1 produttore e 1 consumatore! Se ho piu’ produttori o piu’ consumatori, devo usare la mutua esclusione! • Classe condivisa: import java. io. *; public class Buffer{ private int buf[]= new int[10]; private int in, out; Buffer(){ in=0; out=0; } int get_in(){ return in; } int get_out(){ return out; } void put_in(int a){ in=a; } void put_out(int b){ out=b; } void put(int i, int f){ buf[i]=f; } int get(int i){ return (int)buf[i]; } }

Passaggio di parametri tra Thread • Produttore: public class Prod extends Thread{ // produttore

Passaggio di parametri tra Thread • Produttore: public class Prod extends Thread{ // produttore Buffer buf; Random r; Prod(Buffer p){ this. buf=p; r=new Random(); } public void run(){ int val; while(true) { val=r. next. Int(); while (buf. get_out()==((buf. get_in()+1)%10)); buf. put(buf. get_in(), val); System. out. println("nproduco "+val+" in="+buf. get_in()); buf. put_in((buf. get_in()+1)%10); } } } • Consumatore public class Cons extends Thread{ // consumatore Buffer buf; Cons(Buffer p){ this. buf=p; } public void run(){ int val; while(true) { while (buf. get_out()==buf. get_in()); val=buf. get(buf. get_out()); System. out. println("nconsumo "+val+" out="+buf. get_out()); buf. put_out((buf. get_out()+1)%10); } } }

Passaggio di parametri tra Thread • Altro consumatore public class Cons 1 extends Thread{

Passaggio di parametri tra Thread • Altro consumatore public class Cons 1 extends Thread{ // consumatore Buffer buf; Cons 1(Buffer p){ this. buf=p; } public void run(){ int val; while(true) { while (buf. get_out()==buf. get_in()); val=buf. get(buf. get_out()); System. out. println("ncons_1 "+val+“ out="+buf. get_out()); buf. put_out((buf. get_out()+1)%10); } } } • Programma principale: public class pc{ public static void main(String[] a){ Buffer buf=new Buffer(); Prod c=new Prod(buf); Cons t=new Cons(buf); Cons 1 z=new Cons 1(buf); c. start(); t. start(); z. start(); } }

Passaggio di parametri e sincroniuzzazione tra Thread • Una soluzione al problema e’ quello

Passaggio di parametri e sincroniuzzazione tra Thread • Una soluzione al problema e’ quello di usare un arbitro software. In questo caso si usa l’alternanza stretta. La classe condivisa e’ la seguente: import java. io. *; public class Buffer. Plus{ private int buf[]= new int[10]; private int in, out; private int blk; Buffer. Plus(){ in=0; out=0; blk=0; } int get_in(){ return in; } int get_out(){ return out; } void put_in(int a){ in=a; } void put_out(int b){ out=b; } void put(int i, int f){ buf[i]=f; } int get(int i){ return (int)buf[i]; } int getblk(){ return (int)blk; } void putblk(int a){blk=a; } }

Passaggio di parametri e sincronizzazione tra Thread • Primo consumatore: import java. util. *;

Passaggio di parametri e sincronizzazione tra Thread • Primo consumatore: import java. util. *; public class Cons. Plus extends Thread{ // consumatore Buffer. Plus buf; Cons. Plus(Buffer. Plus p){ this. buf=p; } public void run(){ int val; while(true) { while( buf. getblk() == 0); { while (buf. get_out()==buf. get_in()); val=buf. get(buf. get_out()); System. out. println("nconsumo "+val+“ out="+buf. get_out()); buf. put_out((buf. get_out()+1)%10); } buf. putblk(0); } } }

Passaggio di parametri e sincronizzazione tra Thread • Secondo consumatore: import java. util. *;

Passaggio di parametri e sincronizzazione tra Thread • Secondo consumatore: import java. util. *; public class Cons 1 Plus extends Thread{ // consumatore Buffer. Plus buf; Cons 1 Plus(Buffer. Plus p){ this. buf=p; } public void run(){ int val; while(true) { while(buf. getblk()==1); { while (buf. get_out()==buf. get_in()); val=buf. get(buf. get_out()); System. out. println("ncons_1 "+val+“ out="+buf. get_out()); buf. put_out((buf. get_out()+1)%10); } buf. putblk(1); } } }

Monitors in Java • • La soluzione alla mutua esclusione in Java e’ data

Monitors in Java • • La soluzione alla mutua esclusione in Java e’ data dall’uso dei monitor (Hoare) I monitor sono realizzati mediante i metodi synchronized: il thread che esegue un metoro synchronized di un oggetto deve preventivamente acquisire il monito associato all’oggetto Il monitor viene rilasciato all’uscita dal metodo All’interno di un metodo synchronized e’ possibile sospendere il thread che sta eseguendo attraverso l’uso dello statement wait() Wait provoca la sospensione del thread ed il rilascio del monitor da lui posseduto I thread sospesi possono essere risvegliati usando i metodi notify() e notify. All() Questi metodi possono essere invocati solo all’interno di metodi synchronized L’effetto di notify() e notify. All() e’ la ripresa dell’esecuzione dei thread sospesi sul monitor detenuto dal thread che esegue la notify o la notify. All

Esempio di monitor in Java • • Riconsideriamo l’esempio del produttore/consumatore: Classe condivisa: import

Esempio di monitor in Java • • Riconsideriamo l’esempio del produttore/consumatore: Classe condivisa: import java. io. *; public class Buffer. Mon { private int buf[]= new int[10]; private int in, out; Buffer. Mon(){ in=0; out=0; } synchronized void put(int f) { if( ((in+1)%10) == out) try{ wait(); } catch(Interrupted. Exception e){}; buf[in]=f; System. out. println("produco "+f+" in="+in); in=(in+1)%10; notify(); } synchronized int get() { if(out == in) try{ wait(); } catch(Interrupted. Exception e){}; int val=buf[out]; System. out. print("get "+val+" out="+out); out=(out+1)%10; notify(); return(val); } }

Esempio di monitor in Java • Consumatore import java. util. *; public class Cons.

Esempio di monitor in Java • Consumatore import java. util. *; public class Cons. Mon extends Thread{ // consumatore Buffer. Mon buf; Cons. Mon(Buffer. Mon p){ this. buf=p; } public void run(){ while(true) { int val=buf. get(); System. out. println("cons = "+val); } } } • Altro cinsumatore import java. util. *; public class Cons 1 Mon extends Thread{ // consumatore Buffer. Mon buf; Cons 1 Mon(Buffer. Mon p){ this. buf=p; } public void run(){ while(true) { int val=buf. get(); System. out. println("cons_1 = "+val); } } }

Esempio di monitor in Java • Produttore: import java. util. *; public class Prod.

Esempio di monitor in Java • Produttore: import java. util. *; public class Prod. Mon extends Thread{ // produttore Buffer. Mon buf; Random r; Prod. Mon(Buffer. Mon p){ this. buf=p; r=new Random(); } public void run(){ while(true) { buf. put(r. next. Int()); } } } • Principale: public class pc. Mon{ public static void main(String[] a){ Buffer. Mon buf=new Buffer. Mon(); Prod. Mon c=new Prod. Mon(buf); Cons. Mon t=new Cons. Mon(buf); Cons 1 Mon z=new Cons 1 Mon(buf); c. start(); t. start(); z. start(); } }

Breve confronto C++/Java n Somiglianze q q q n paradigma a oggetti incapsulamento ereditarietà

Breve confronto C++/Java n Somiglianze q q q n paradigma a oggetti incapsulamento ereditarietà polimorfismo sintassi molto simile (ad es. for, while, switch) Differenze q gestione della memoria n q q a carico del sistema (garbage collector) o del programmatore uso dei puntatori portabilità del codice compilato velocità di esecuzione