18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

31
18 novembre 20 03 1 I nomi in Java I nomi in Java F. Bombi 18 novembre 2003

Transcript of 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

Page 1: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003 1

I nomi in JavaI nomi in Java

F. Bombi

18 novembre 2003

Page 2: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

2

Le variabiliLe variabili

Una variabile è una posizione in memoria alla quale è associato un determinato tipo che può essere o un tipo primitivo o un riferimento

Una variabile ha sempre un valore compatibile con il suo tipo

Il valore di una variabile può essere modificato da un’assegnazione oppure da un operatore di incremento (++) o decremento (--)

Page 3: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

3

I 7 tipi di variabiliI 7 tipi di variabili

Variabile di classe: un campo di una classe con l’attributo static

Variabile di esemplare: un campo di una classe senza l’attributo static

Componenti di un array: sono variabili senza nome che vengono create quando si crea un array destinate a contenere i singoli elementi dell’array

Parametro di un metodo: nome di una variabile che sarà inizializzata con il valore dell’argomento passato al metodo

Parametro di un costruttore: come per un metodo Parametro di un gestore di eccezione Variabile locale: variabile dichiarata all’interno di un blocco

Page 4: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

4

Variabile di classeVariabile di classe

Una variabile di classe viene creata al momento in cui la classe viene caricata nella memoria della macchina virtuale e in assenza di indicazione contraria viene inizializzata a 0, false o null

Di una variabile di classe esiste un solo esemplare condiviso da tutti gli oggetti della classe

L’uso di variabili di classe è limitato a casi molto specifici ad esempio per costanti simboliche condivise oppure per contare quanti esemplari di una classe sono stati creati o per segnalare ad altri esemplari di una classe che si è invocato un metodo

class A{ static int vs; public A () {vs++;} …}…A uno = new A();…A due = new A();…System.out.println(A.vs);

Page 5: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

5

Variabili di esemplareVariabili di esemplare

Le variabili di esemplare (instance variable) rappresentano il caso più comune di campo di una classe

Un nuova variabile di esemplare viene creata ogni volta che si crea un esemplare della classe che la contiene, in assenza di indicazione contraria, le variabili di esemplare sono sempre inizializzate a 0, false o null

Un variabile di esemplare cessa di esistere quando l’oggetto che la contiene non è più indirizzato da un riferimento (lo spazio di memoria è a questo punto soggetto a garbage collection)

Page 6: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

6

Componenti di un arrayComponenti di un array

Le componenti di un array sono variabile senza nome che vengono create al momento della creazione dell’array.

Sono inizializzati a 00, falsefalse o nullnull

Fare attenzione che se si crea un array di oggetti la creazione dell’array crea solo i riferimenti agli oggetti (inizializzati a null) e non gli oggetti che dovranno essere esplicitamente creati uno per uno

class Coppia{ int a; int b;}…Coppia[] v = new Coppia[4];v[0].a = 25; // null pointer

class Coppia{ int a; int b;}…Coppia[] v = new Coppia[4];for(int i=0;i<4;i++) v[i] = new Coppia();v[0].a = 25; // OK

Page 7: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

7

I parametriI parametri

Un parametro attribuisce un nome all’interno di un metodo all’argomento con il quale il metodo viene invocato

Un parametro, analogamente ad una variabile locale, viene creato al momento dell’invocazione del metodo e cessa di esistere quando si conclude il blocco che costituisce il corpo del metodo

Un parametro viene inizializzato con il valore dell’argomento usato al momento della chiamata del metodo

Java di conseguenza utilizza sempre e solo il passaggio dei parametri per valore

class A{ void m(int i) { int locale; locale = i*i; }} …

A x = new A();int k = 25; x.m(k);x.m(3);

parametro

argomentoi = k = 25

Page 8: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

8

static void scambia (int x, int y) { int tmp = x; x = y; y = tmp; }

static void scambia (Integer x, Integer y) { Integer tmp = x; x = y; y = tmp; }

static void scambia (MioInt x, MioInt y) { int tmp = x.valore; x.valore = y.valore; y.valore = tmp; }}class MioInt{ int valore; public String toString() { return Integer.toString(valore); }}

// Il passaggio dei parametri in Java

public class Param{ public static void main (String[] arg) { int i = 1; int j = 2; System.out.println("Prima: i= " + i + " j= " + j); scambia(i, j); System.out.println("Dopo1: i= " + i + " j= " + j); Integer ii = new Integer(i); Integer jj = new Integer(j); scambia(ii, jj); System.out.println("Dopo2: i= " + ii + " j= " + jj); MioInt iii = new MioInt(); iii.valore = i; MioInt jjj = new MioInt(); jjj.valore = j; scambia(iii, jjj); System.out.println("Dopo3: i= " + iii + " j= " + jjj); }

Il passaggio dei parametri per valore è unidirezionaleIl passaggio dei parametri per valore è unidirezionale

Prima: i= 1 j= 2Dopo1: i= 1 j= 2Dopo2: i= 1 j= 2Dopo3: i= 2 j= 1

Page 9: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

9

int i = 1;int j = 2;

1i

2j

scambia(i, j); static void scambia (int x, int y) { int tmp = x; x = y; y = tmp; }

?x

?y

inizializza?

tmp11

21

2

al ritorno del metodo scambia le variabilii e j sono immutate

Page 10: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

10

Integer ii = new Integer(1);Integer jj = new Integer(2);

ii

jj

scambia(ii,jj);

inizializzax

y

al ritorno del metodo scambia i riferimentiii e jj sono immutati

1

2

static void scambia (Integer x, Integer y) { Integer tmp = x; x = y; y = tmp; }

tmp

Page 11: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

11

Valore?

jjj

Valore?

iii

MioInt iii = new MioInt(); iii.valore = 1;MioInt jjj = new MioInt(); jjj.valore = 2;

scambia(iii, jjj);

al ritorno del metodo scambia i riferimenti

iii e jjj non sono cambiatisono però stati scambiati i campi

inizializza

x

y1

2

tmp

static void scambia (MioInt x, MioInt y) { int tmp = x.valore; x.valore = y.valore; y.valore = tmp; }

1

2 1

Page 12: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

12

Come ritornare un valoreCome ritornare un valore

Il meccanismo del passaggio dei parametri ad un metodo essendo per valore è unidirezionale, il parametro viene inizializzato con l’argomento al momento della chiamata, se il parametro viene modificato l’argomento rimane immutato

Un metodo può restituire una sola variabile con la clausola returnreturn, il tipo di valore restituito deve essere indicato nella dichiarazione del metodo

Page 13: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

13

Uso di variabili globaliUso di variabili globali All’interno di una classe due metodi possono

scambiarsi dati utilizzando un campo della classe come variabile condivisa o globale

Questa forma di comunicazione non può essere usata fra metodi di classi diverse in quanto gli esemplari di classi diverse non accedono agli stessi campi

Ricordarsi infine che un metodo quando è invocato conosce i campi dell’esemplare della classe individuata dal riferimento usato per invocare il metodo detto talvolta parametro implicitoparametro implicito

Il valore del parametro implicito è accessibile con la clausola thisthis

Page 14: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

14

argomentoactual parameterparametro reale

parametroformal parameterparametro formale

all’attivazione o chiamata del metodoil valore dell’argomento viene utilizzato

per inizializzare il corrispondente parametro

return valore;

Alla terminazione del metodo il controllo viene passato alpunto di chiamata. I valore dei parametri vengono persi, inquanto si tratta di variabili locali allocate sul run-time stack(ma non vengono persi eventuali effetti collaterali).Il metodo può restituire un singolo valore

Page 15: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

15

Pacchetti (Pacchetti (packagepackage)) Una applicazione Java si compone di uno o più pacchetti Un pacchetto è un insieme di file (unità compilabili), un

pacchetto può essere organizzato gerarchicamente in sottopacchettisottopacchetti

In assenza di indicazioni contrarie i file contenuti nel directory di lavoro costituiscono un pacchetto senza pacchetto senza nomenome

Tutti gli esempi visti a lezione sono realizzati come pacchetti senza nome

Abbiamo visto in molti esempi come importare un componente di un pacchetto di libreria o l’intero pacchetto

Page 16: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

16

I nomi in JavaI nomi in Java Tutte le entità usate in un programma Java sono

individuate da nominomi, dette identificatoriidentificatori, composti da stringhe di caratteri alfanumerici con il primo carattere alfabetico

Ogni nome deve essere dichiaratodichiarato prima di essere usato, la dichiarazione specifica l’entità cui il nome si riferisce e chi può accedere al nome qualificandolo

Ogni nome semplicesemplice è riconosciuto in una porzione del programma detta il suo scopescope

Il significato di un nome è stabilito dal contestocontesto nel quale viene usato

Page 17: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

17

Le entità individuate da un nome possono essere– Una classe– Un’interfaccia– Un membro di una classe (campo o metodo)– Un parametro di un metodo, di un costruttore o

di un gestore di eccezione– Una variabile locale

Un nome semplicesemplice è costituito da un solo identificatore

Un nome qualificatoqualificato è costituito da più identificatori separati da un • (punto)

public class Coppia implements Comparablepublic class Coppia implements Comparable{ public Comparable chiave;{ public Comparable chiave; … …}}

public interface Stackpublic interface Stack{ void push (Object x);{ void push (Object x); … …}}

public class Coppia implements Comparablepublic class Coppia implements Comparable{ public Comparable chiave;{ public Comparable chiave; … … public String toString () { return chiave.toString() + ":" + attributo.toString(); }public String toString () { return chiave.toString() + ":" + attributo.toString(); }}}

public class Coppia implements Comparablepublic class Coppia implements Comparable{ …{ … public Coppia (Comparable c, Object a) { chiave = c; attributo = a; }public Coppia (Comparable c, Object a) { chiave = c; attributo = a; } public int compareTo (Object x) { return chiave.compareTo(((Coppia)x).chiave); }public int compareTo (Object x) { return chiave.compareTo(((Coppia)x).chiave); }}}

public static void main (String[] arg) throws IOExceptionpublic static void main (String[] arg) throws IOException { BufferedReader in = new BufferedReader(new FileReader(arg[0]));{ BufferedReader in = new BufferedReader(new FileReader(arg[0])); int n = 0;int n = 0; int somma = 0;int somma = 0; … …

while ((str = in.readLine()) != null)while ((str = in.readLine()) != null) { token = new StringTokenizer(str, ":");{ token = new StringTokenizer(str, ":"); int matricola = Integer.parseInt(token.nextToken());int matricola = Integer.parseInt(token.nextToken()); String nome = token.nextToken();String nome = token.nextToken(); dati[n++] = new Studente(nome, matricola);dati[n++] = new Studente(nome, matricola); }}

Page 18: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

18

Lo Lo scopescope Lo scope di una dichiarazione è la regione di un

programma nell’ambito della quale ci si può riferire ad una entità con il nome semplice

Lo scope del nome di una classe è l’intero pacchetto nel quale la classe compare

Lo scope di un membro di una classe è l’intera classe nella quale è dichiarato

Lo scope del nome di un parametro di un metodo o di un costruttore è l’intero corpo del metodo o del costruttore

Lo scope di una variabile locale dichiarata in un blocco si estende fino alla fine del blocco

Lo scope di una variabile locale dichiarata nell’inizializzazione di un ciclo for for si estende al solo corpo del ciclo

public class Coppia implements Comparablepublic class Coppia implements Comparable{ public Object attributo;{ public Object attributo; public Coppia (Comparable c, Object a) { chiave = c; attributo = a; }public Coppia (Comparable c, Object a) { chiave = c; attributo = a; } public int compareTo (Object x) { return chiave.compareTo(((Coppia)x).chiave); }public int compareTo (Object x) { return chiave.compareTo(((Coppia)x).chiave); } public String toString () { return chiave.toString() + ":" + attributo.toString(); }public String toString () { return chiave.toString() + ":" + attributo.toString(); } public Comparable chiave;public Comparable chiave;}}

int[] r = c.contiene();int[] r = c.contiene(); for (int i = 0; i < r.length; i++)for (int i = 0; i < r.length; i++) System.out.print(r[i] + ", ");System.out.print(r[i] + ", "); System.out.println();System.out.println(); c.togli(1);c.togli(1); r = c.contiene();r = c.contiene(); for (int i = 0; i < r.length; i++)for (int i = 0; i < r.length; i++) System.out.print(r[i] + ", ");System.out.print(r[i] + ", "); System.out.println();System.out.println(); for (int i = 0; i < 32; i++)for (int i = 0; i < 32; i++) if (c.appartiene(i))if (c.appartiene(i)) System.out.print("1");System.out.print("1"); elseelse System.out.print("0");System.out.print("0");

Page 19: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

19

Il controllo dell’accessoIl controllo dell’accesso

L’uso di nomi qualificatinomi qualificati consente di controllare l’accesso ai membri di una classe indipendentemente dallo scope, si danno 4 casi:– defaultdefault: accesso a livello di package– publicpublic: accesso da qualsiasi punto– privateprivate: accesso possibile solo dall’interno

della classe nella quale il nome è dichiarato– protectedprotected: accesso a livello di package e

nelle sottoclassi che estendono la classe

In genere i In genere i campicampi di una classe sono di una classe sono privateprivate (o (oprotected) in quanto si vuole che solo i metodiprotected) in quanto si vuole che solo i metodidella classe possano modificare il valore dei campidella classe possano modificare il valore dei campimentre i mentre i metodimetodi sono sono publicpublic perché devono poter perché devono poter essere utilizzati dall’esterno della classeessere utilizzati dall’esterno della classe

Page 20: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

20

Oscurare una dichiarazioneOscurare una dichiarazione

La dichiarazione di un nome all’interno di un blocco contenuto in un altro blocco può oscurare la dichiarazione più esterna

In genere è bene evitare di dichiarare la stessa variabile in blocchi diversi con significati diversi per evitare confusione (il compilatore non si il compilatore non si confonde!confonde! ma il lettore può rimanere confuso)

Vediamo ora un esempio di una dichiarazione che ne oscura un’altra in una situazione particolarmente insidiosa

Page 21: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

21

public class StackAr implements Stackpublic class StackAr implements Stack{ private Object[] v;{ private Object[] v; private int sp;private int sp; private static final int MAX = 10;private static final int MAX = 10; public StackAr ()public StackAr () { sp = 0;{ sp = 0; Object[] v = new Object[MAX];Object[] v = new Object[MAX]; }} public StackAr (int max)public StackAr (int max) { sp = 0;{ sp = 0; v = new Object[max];v = new Object[max]; }} public void push (Object x) { v[sp++] = x; }public void push (Object x) { v[sp++] = x; } public Object pop () throws Underflowpublic Object pop () throws Underflow { if (sp == 0){ if (sp == 0) throw new Underflow("Pop di stack vuoto");throw new Underflow("Pop di stack vuoto"); elseelse return v[--sp];return v[--sp]; }} public Object testa () throws Underflowpublic Object testa () throws Underflow { if (sp == 0){ if (sp == 0) throw new Underflow("Testa di stack vuoto");throw new Underflow("Testa di stack vuoto"); elseelse return v[sp-1];return v[sp-1]; }} public boolean vuoto () { return sp == 0; }public boolean vuoto () { return sp == 0; }}}

Page 22: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

22

I paradigmi di programmazioneI paradigmi di programmazione

Un programma deve essere comprensibile sia al compilatore (e alla macchina) sia all’uomo

È importante utilizzare paradigmi (modelli) di programmazione che aiutino a scrivere programmi corretti e facili da mantenere e modificare

Nel tempo si sono sviluppati molti paradigmi diversi nel tentativo di rendere più facile la produzione di programmi corretti e mantenibili

Page 23: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

23

La decomposizione funzionaleLa decomposizione funzionale

Per decomposizione funzionale si intende la tecnica con la quale si risolve un problema attraverso la composizione di sottoprogrammi o funzioni

Ad esempio dovendo leggere ed elaborare dei dati si scrive un sottoprogramma che legge i dati, uno che gli elabora ed un terzo che stampa i risultati

Il primo linguaggio che ha messo a disposizione strumenti per facilitare la decomposizione funzionale è stato il Fortran IV (fine anni ’50)

Page 24: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

24

La programmazione strutturataLa programmazione strutturata

Un programma si dice strutturato se è realizzato dalla composizione delle due sole strutture (o loro derivazione) if-then-elseif-then-else e while-dowhile-do

I linguaggi di programmazione moderni (sviluppati dopo l’invenzione del Pascal, inizio anni ‘70) sono per loro natura strutturati e quindi obbligano ad utilizzare naturalmente la programmazione strutturata

L’idea è così connaturata con i linguaggi moderni quali il C/C++ o Java che non è quasi più il casi di parlare di programmazione strutturata

Page 25: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

25

La modularizzazioneLa modularizzazione Per affrontare la costruzione di un grande progetto software

è necessario disporre di strumenti che consentano di costruire il software sotto forma di componenti indipendenti detti talvolta modulimoduli

Pascal (in origine) non consentiva nessuna forma di modularizzazione, un programma doveva essere sempre pensato come monolitico in quanto doveva contenere al suo interno tutte le procedure e funzioni necessarie

Il linguaggio C non dispone intrinsecamente di strumenti per la modularizzazione ma non la impedisce, è quindi possibile realizzare in C software modulare utilizzando le funzioni di macro elaborazionemacro elaborazione fornite dal linguaggio e strumenti esterni quali makemake per automatizzare le operazioni di espansione delle macro, compilazione e collegamento

Page 26: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

26

Modularizzazione (segue)Modularizzazione (segue)

I linguaggi Ada e Modula 2 sono stati progettati in modo da facilitare e rendere controllabile la modularizzazione. Hanno però avuto uno sviluppo limitato, il primo solo nell’ambiente delle commesse militari e spaziali, il secondo solo in un limitato ambiente accademico

Alcune estensione del linguaggio C quali C++ e in particolar modo il linguaggio orientato agli oggetti Eifell sono stati pensati in modo da facilitare la modularizzazione

Page 27: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

27

La programmazione orientata agli oggettiLa programmazione orientata agli oggetti

I linguaggio orientati agli oggetti mettono a disposizione una ricco repertorio di strumenti per la realizzazione di software in forma modulare

Package Incapsulamento (o information hiding)PolimorfismoEreditarietà

Page 28: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

28

Packages -> PacchettiPackages -> Pacchetti Un programma in Java è organizzato come un insieme di

pacchetti Ogni pacchetto ha un suo insieme di nomi per i tipitipi (classi

e interfacce) Un tipotipo dichiarato in un pacchetto è accessibile al di fuori

del pacchetto in cui è stato dichiarato solo se ha l’attributo publicpublic

I pacchetti sono organizzati in forma gerarchica come pacchetti e sottopacchetti

I pacchetti possono essere memorizzati come file o in un database

L’organizzazione in pacchetti facilita la modularizzazione isolando le scelte dei nomi di un pacchetto da quelle di ogni altro pacchetto

Page 29: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

29

IncapsulamentoIncapsulamentoPer incapsulamentoincapsulamento o information hidinginformation hiding si

intende la caratteristica di un linguaggio che consente di nascondere all’utente di un pacchetto (o anche in particolare di una sola classe) i dettagli con cui le funzionalità sono realizzate

Java consente di progettare pacchetti e classi in modo da nascondere in modo completo i dettagli realizzativi all’utente

Page 30: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

30

PolimorfismoPolimorfismo Il polimorfismopolimorfismo è la proprietà di un linguaggio orientato ad

oggetti per cui la decisione di quale metodo viene invocato tramite un riferimento viene stabilito al momento dell’esecuzione del programma in funzione del valore effettivamente assegnato al riferimento (in sintesi si parla di late bindinglate binding)

Java è intrinsecamente polimorfo Una forma elementare di polimorfismo è anche offerta dal

sovraccaricosovraccarico (overloadingoverloading) del nome di un metodo. Notare che il sovraccarico non richiede il late binding in quanto il compilatore può decidere quale metodo invocare dal confronto della forma della chiamata con la firma del metodo (nome e elenco del tipo degli argomenti)

Page 31: 18 novembre 20031 I nomi in Java F. Bombi 18 novembre 2003.

18 novembre 2003

31

EreditarietàEreditarietà

L’ereditarietà consente di costruire una nuova classe che estende le funzionalità di un’altra classe senza avere accesso al codice sorgente della classe che si vuole estendere

Ereditarietà e polimorfismo sono funzionalità da utilizzare in modo coordinato

La programmazione orientata ad oggetti si caratterizza dalla possibilità di costruire l’estensione di una classe senza disporre del codice sorgente della classe da estendere combinata con la realizzazione del polimorfismo mediante late binding