Il linguaggio Java
Gianpaolo Cugola
[email protected]
Gianpaolo Cugola
1
Sgomberiamo il campo dai dubbi
• Cosa non è Java:
– Non è un linguaggio per “animare” il WWW
– Non è una versione ridotta del C+ +
– Non è lo strumento che segnerà la fine di Microsoft
• Cosa è Java
– Un moderno linguaggio di programmazione OO…
– Orientato alla programmazione di applicazioni
“network-centric”
Gianpaolo Cugola
Gianpaolo Cugola
2
Perché Java
• Il problema:
– L’inadeguatezza dello schema di sviluppo tradizionale
(binary distribution) in ambienti distribuiti e multipiattaforma
• La soluzione:
– Java, un linguaggio O.O. per lo sviluppo di
applicazioni “architecture independent”, robuste,
adattabili, scalabili ed efficienti
Gianpaolo Cugola
3
Java: caratteristiche generali - 1
• Familiare:
– La sintassi di Java ricalca la sintassi del C++
– Un programmatore C++ non incontra grosse difficoltà
ad imparare il linguaggio Java
• Semplice:
– Programmare usando Java è molto più semplice di
programmare usando altri linguaggi OO (C++)
• Un buon programmatore Java è più produttivo di un buon
programmatore C+ +
Gianpaolo Cugola
Gianpaolo Cugola
4
Java: caratteristiche generali - 2
• Object-oriented:
– Java è un linguaggio OO “puro” con ereditarietà, binding
dinamico ed oggetti gestiti tramite riferimenti
– Il costrutto delle “interfaces” fornisce le potenzialità
dell’ereditarietà multipla senza alcun problema di duplicazione
di codice
• Portabile:
– La specifica del linguaggio non contiene componenti
“implementation dependent”
Gianpaolo Cugola
5
Java: caratteristiche generali - 3
• Architecture neutral:
– L’applicazione viene compilata in un linguaggio intermedio
(Java ByteCode) che viene interpretato
– L’interprete nasconde le caratteristiche peculiari dell’hardware e
del sistema operativo
– Lo stesso codice “oggetto” può essere eseguito su tutte le
piattaforme per le quali venga fornito un interprete Java
(attualmente Solaris, Windows NT/ 95, MacOS, OS/ 2, AIX, e
Linux)
Gianpaolo Cugola
Gianpaolo Cugola
6
Java: caratteristiche generali - 4
• Dinamico:
– Le fasi di loading e linking avvengono a run-time
• Robusto:
– Java è un linguaggio fortemente tipizzato con numerose
caratteristiche che diminuiscono la possibilità di
introdurre errori nelle applicazioni, tra le quali:
• assenza di puntatori
• abbondanza di controlli run-time (rispetto dei limiti degli array,
controlli di tipo, controlli sul codice caricato dinamicamente,
ecc.)
• gestione automatica della memoria (garbage collecting)
Gianpaolo Cugola
7
Java: caratteristiche generali - 5
• Multi-threaded:
– Java supporta la gestione dei “thread” a livello di linguaggio,
oltre che di macchina virtuale, fornendo la possibilità di creare
facilmente applicazioni concorrenti
Gianpaolo Cugola
Gianpaolo Cugola
8
L’ambiente Java
Byte code
Loader
Java Source
Java Compiler
Java Byte
Code
Byte code
Verifier
Byte Code moves
through network
or file system
Interpreter
Machine Code
Generator (JIT)
Run time
Hardware/OS
Gianpaolo Cugola
9
Java - il primo programma
file: HelloWorld.java
public class HelloWorld {
public static void main(String args[]){
System.out.println(“Hello world!”);
}
}
Gianpaolo Cugola
Gianpaolo Cugola
10
Compilazione ed esecuzione
c:\classes>javac HelloWorld.java
c:\classes>java HelloWorld
HelloWorld!
c:\classes>
Gianpaolo Cugola
11
La struttura di un programma Java nozioni preliminari
• Un programma Java è organizzato come un
insieme di classi
• Classi diverse possono essere raggruppate
all’interno della stessa “Compilation unit”
• Il programma principale è rappresentato da un
metodo speciale della classe il cui nome coincide
con il nome del programma
Gianpaolo Cugola
Gianpaolo Cugola
12
Java - il primo programma grafico
File: HelloWorldWindow.java
import java.awt.*;
package examples,
class HelloWorldWindow {
public static void main(String args[]) {
Frame f=new Frame("HelloWorldWindow");
f.add(new Label("HelloWorld!",Label.CENTER),"Center");
f.pack();
f.setVisible(true);
}
}
Gianpaolo Cugola
13
Compiliazione ed esecuzione
c:\classes>cd examples
c:\classes\examples>javac
HelloWorldWindow.java
c:\classes\examples>cd ..
c:\classes>java examples.HelloWorldWindow
c:\classes>
Gianpaolo Cugola
Gianpaolo Cugola
14
La struttura di un programma Java
• Package
– Ogni package contiene una o più compilation unit
– Il package introduce un nuovo ambito di visibilità dei nomi
• Compilation unit
– Ogni compilation unit contiene una o più classi o interfaccie
delle quali una sola pubblica
• Classi e interfaccie
• Relazioni con il file system
– package ⇔ directory
– compilation unit ⇔ file
Gianpaolo Cugola
15
Il linguaggio Java in dettaglio
• Costrutti per la programmazione “in the small”
– Il type system di Java
• Tipi predefiniti e relative costanti ed operatori
• Tipi definiti dall’utente
– Dichiarazione di variabili
– Istruzioni per il controllo di flusso
• Costrutti per la programmazione “in the large”
– Classi
– Interfaccie
– Packages
Gianpaolo Cugola
Gianpaolo Cugola
16
I commenti in Java
// questo è un commento che termina con la fine della linea
/* questo è un commento che può
spaziare su più linee */
Gianpaolo Cugola
17
Identificatori
• Gli identificatori (nomi di classi, variabili, attributi,
metodi ecc.) sono sequenze alfanumeriche che:
– Devono iniziare con una lettera o con il carattere '_'
– Il resto dell’identificatore può contenere sia lettere che numeri,
o il carattere '_'
– Non devono coincidere con una delle parole riservate
• Esempi
Ok: HelloWorld helloWorld h ello_world __prova __PROVA prova1
prova1a prova2
Errati: 2prova +prova prova + hello-world hello? prova-1
• Java è “case sensitive”
Gianpaolo Cugola
Gianpaolo Cugola
18
Le costanti
• Costanti intere:
123 256789L 0xff34d 0xcafebabeL 03477 07352367L
• Costanti reali:
123.75
0.12375e+3
12375.0e-2f
1.0E-5
123.75f
123.75F
123.75D
• Costanti boolean:
true
false
• Costanti carattere:
’a’
’%’
’\t’
’\n’
’\\’
’\’’
’\123’
• Costanti di tipo stringa:
”prova”
”prova\n”
”prova( \”aaa\” )”
Gianpaolo Cugola
19
Il tipe system di Java
• Java è un linguaggio fortemente tipizzato
• Distinguiamo tra:
– tipi primitivi
– tipi “riferimento”
Gianpaolo Cugola
Gianpaolo Cugola
20
I tipi primitivi
• Tipi numerici:
–
–
–
–
–
–
byte:
short:
int:
long:
float:
double:
8 bit
16 bit
32 bit
64 bit
32 bit, secondo specifica IEEE754
64 bit, secondo specifica IEEE754
• Altri tipi:
– boolean:
– char:
true o false
16 bit, carattere Unicode
Gianpaolo Cugola
21
Operatori per i tipi numerici - 1
• Operatori unari
– operatori “di segno”
+x
-x
– incremento e decremento (prefissi e/ o postfissi)
++x
--x
x++
x--
– operatore di complemento binario (valido per soli tipi
“interi”): ~x
Gianpaolo Cugola
Gianpaolo Cugola
22
Operatori per i tipi numerici - 2
• Operatori binari
– validi per tutti i tipi numerici
x+y
x-y
x*y
x/y
x%y
– validi per i soli tipi “interi”
x<<y
x>>y
x>>>y
x&y
x|y
x^y
• Operatori di confronto
x==y
x!=y
x<y
x>y
x<=y
x>=y
Gianpaolo Cugola
23
Operatori per il tipo boolean
• Operatore unario
– negazione logica: !x
• Operatori binari
– operatori standard
x&y
x|y
x^y
– operatori con semantica condizionale
x&&y
x||y
– operatori di confronto
x==y
Gianpaolo Cugola
Gianpaolo Cugola
x!=y
24
Operatori per il tipo char
• Operatori di confronto
x==y
x!=y
x<y
x>y
x<=y
x>=y
Gianpaolo Cugola
25
Gli operatori di auto assegnamento
• E` possibile usare l’operatore:
x ?= y
al posto di un qualsiasi operatore ? che sia lecito
utilizzare nell’espressione:
x=x?y
• Tale espressione equivale alla precedente x?=y
• Esempi:
x+=5
x*=2
Gianpaolo Cugola
Gianpaolo Cugola
equivale a
equivale a
x=x+5
x=x*2
26
Altri operatori
• Operatore condizionale
– si applica a tutti i tipi
<condizione> ? <valore1> : <valore2>
• L’assegnamento come operatore
x=y=3
(y=3)==3
• L’operatore di concatenazione tra stringhe
– si applica a tutti i tipi
”pippo”+2
”pippo”+2.54
Gianpaolo Cugola
27
I tipi riferimento
• Tipi array
• Tipi definiti dall’utente
Gianpaolo Cugola
Gianpaolo Cugola
28
Tipo array
• Dato un tipo T (predefinito o definito dall’utente)
un array di T è definito come:
T[]
• Similmente sono dichiarati gli array
multidimensionali:
T[][]
T[][][]
…
• Esempi:
int[]
float[][]
Persona[]
Gianpaolo Cugola
29
Tipi definiti dall’utente
• Classi
• Interfaccie
... i dettagli nel seguito
Gianpaolo Cugola
Gianpaolo Cugola
30
Dichiarazione e inizializzazione di
variabili
• Dichiarazione
int i;
int i,j;
Persona p;
float f1,f2;
double d;
• Inizializzazione
int i=0;
int i=0, j=4;
Persona p=new Persona();
float f1=1.23f, f2=127.2f;
double d=1.23;
Gianpaolo Cugola
31
Dichiarazione e inizializzazione di
variabili: gli array
• Dichiarazione:
int[] ai1, ai2;
float[] af1;
double ad[];
Persona[][] ap;
• Inizializzazione:
int[] ai={1,2,3};
double[][] ad={{1.2, 2.5}, {1.0, 1.5}}
Gianpaolo Cugola
Gianpaolo Cugola
32
Dichiarazione di array ed allocazione di
memoria
• La dichiarazione di un array non alloca spazio per gli
elementi dell’array
• L’allocazione si realizza dinamicamente tramite
l’operatore new
int[] i=new int[10], j;
float[][] f=new float[10][10];
Persona[] p=new Persona[30];
j=new int[30];
che alloca però solo lo spazio per l’array, non per i suoi
elementi (tranne nel caso di tipi predefiniti).
Gianpaolo Cugola
33
Istruzioni per il controllo del flusso
•
•
•
•
Sequenza di istruzioni
Blocco di istruzioni
Istruzione condizionale
Cicli
–
–
–
–
Ciclo con uscita all’inizio
Ciclo con uscita alla fine
Ciclo con uscita in mezzo
Ciclo con contatore
• Istruzione switch
Gianpaolo Cugola
Gianpaolo Cugola
34
Sequenza e blocco
• Una sequenza di istruzioni è composta da una
serie di istruzioni separate dal carattere ‘;’
a=3; b=4; c=a*b+3;
• Un blocco di istruzioni è composto da una
sequenza di istruzioni racchiuse da parentesi
graffe
{a=1; b=3; c=a+128;}
– Un blocco di istruzioni è equivalente ad una singola
istruzione
Gianpaolo Cugola
35
Istruzione condizionale
• Permette la scelta tra due diversi percorsi del
flusso di controllo
• Sintassi
if(<condizione>) <istruz.1>
[else <istruz.2>]
• Il ramo else si lega all’istruzione if più vicina
Gianpaolo Cugola
Gianpaolo Cugola
36
Istruzione condizionale: esempi
• Esempio 1:
if(x==5) System.out.println(“x vale 5”);
System.out.println(“fatto!”);
• Esempio 2:
if(x>0 && y>0) System.out.println(“x ed y positivi”);
else if(x>0) System.out.println(“x positivo”);
else if(y>0) System.out.println(“y positivo”);
else System.out.println(“nessuno dei due positivi”);
System.out.println(“fatto!”);
Gianpaolo Cugola
37
Istruzione condizionale: esercizio
• Si scriva un programma che legge un intero su
riga di comando corrispondente ad un mese e
restituisce il numero di giorni in quel mese
– Si faccia uso dell’istruzione:
Integer.parseInt(<string>)
che restituisce un intero a partire da una stringa
Gianpaolo Cugola
Gianpaolo Cugola
38
Ciclo con condizione all’inizio
• Sintassi:
while(<condizione>) <istruzione> ;
• Esempio
int r=5;
while(r>0) {
System.out.println(“HelloWorld!”);
r--;
}
Gianpaolo Cugola
39
Ciclo con condizione all’inizio: esercizio
• Si scriva un programma per il calcolo del fattoriale
• Si scriva un programma che legge un intero da riga di
comando e stampa a video un “triangolo” formato da ‘*’
con base di lunghezza pari all’intero letto
– Si osservi che l’istruzione:
System.out.print(<string>)
stampa la stringa passata come parametro senza andare a capo
Gianpaolo Cugola
Gianpaolo Cugola
40
Ciclo con condizione alla fine
• Sintassi:
do <istruzione> while(<condizione>)
• Esempio:
int r=5;
do {
System.out.println("HelloWorld!");
r--;
} while(r>0);
Gianpaolo Cugola
41
Ciclo con condizione alla fine: esercizio
• Si scriva un programma che esegue il prodotto tra
due numeri secondo l’algoritmo delle somme
ripetute. Si faccia uso del ciclo con condizione alla
fine
Gianpaolo Cugola
Gianpaolo Cugola
42
Ciclo con condizione in mezzo
• E` possibile uscire da un ciclo tramite l’istruzione
break
– Sfruttando questo fatto è possibile creare cicli con
condizione di terminazione in mezzo
• Esempio:
java.io.FileInputStream s=new FileInputStream(“a”);
while(true) {
b=s.read();
if(b==0) break;
System.out.println(b);
}
Gianpaolo Cugola
43
Ciclo con condizione in mezzo: esercizio
• Si scriva un programma che legge un file byte a
byte salvando il contenuto in un array di 500 byte.
Il programma deve terminare quando la fine del
file è stata raggiunta o quando si sono letti 500
byte
– Si osservi che l’istruzione:
s.read()
applicata ad un FileInputStream s restituisce
-1 quando si è raggiunta la fine del file.
Gianpaolo Cugola
Gianpaolo Cugola
44
Ciclo con contatore
• Sintassi:
for(<istr1>; <condiz>; <istr2>) <istr3>
• Equivalente a:
<istr1>;
while(<condiz>) {
<istr3>
<istr2>
}
Gianpaolo Cugola
45
Ciclo con contatore: esempi
• Esempio 1:
int r;
for(r=0; r<5; r++)
System.out.println(“HelloWorld!”);
• Esempio 1 bis:
for(int r=0; r<5; r++)
System.out.println(“HelloWorld!”);
• Esempio 2:
for(int r=0; r<10; r+=2)
System.out.println(“r=”+r);
Gianpaolo Cugola
Gianpaolo Cugola
46
Ciclo con contatore: esercizio
• Si scriva un programma che stampa a video le
tabelline (da 1 a 10). Si faccia uso del ciclo con
contatore
Gianpaolo Cugola
47
Ancora sull’istruzione break
• Sintassi completa di un istruzione break:
– break [<label>]
• Significato:
– restituisce il controllo all’istruzione che include quella con il break e che è
marcata con l’identificatore specificato
• Esempio:
ciclo1 : while(true) {
ciclo2 : while(true) {
leggi(x);
if(x==1) break ciclo1;
else break ciclo2;
}
}
Gianpaolo Cugola
Gianpaolo Cugola
48
Istruzione switch
• Sintassi:
switch(<espressione>) {
case <espr_cost_1> : [<istr_1>;]*
case <espr_cost_2> : [<istr_2>;]*
...
case <espr_cost_n> : [<istr_n>;]*
[ default : [<istr>;]* ]
}
• L’espressione all’interno dello switch deve
essere di tipo char, byte, short, o int
Gianpaolo Cugola
49
Istruzione switch: esempio
public class Prova {
static public void main(String[] args) {
int x=Integer.parseInt(args[0]);
switch(x) {
case 1:
case 2:
case 3: System.out.println(“x pari a 1,2 o 3”);
break;
case 4: System.out.println(“x pari a 4”);
break;
default: System.out.println(“x diverso da 1,2,3 o 4”);
}
}
}
Gianpaolo Cugola
Gianpaolo Cugola
50
Istruzione switch: esercizio
• Si scriva un programma che legge un intero su
riga di comando corrispondente ad un mese e
restituisce il numero di giorni in quel mese. Si usi
l’istruzione switch
Gianpaolo Cugola
51
Conversioni automatiche di tipo
• Promozioni
byte
short
int
long
->
->
->
->
short, int, long, float, double
int, long, float, double
long, float, double
float or double
float
char
->
->
double
int, long, float, double
Gianpaolo Cugola
Gianpaolo Cugola
52
Conversioni forzate: casting
• È possibile forzare una conversione di tipo attraverso
l’operatore di casting:
(<tipo>)<espressione>
• Tra tipi semplici sono consentite le seguenti conversioni
(con perdita di informazione)
short
char
int
long
float
double
byte
->
->
->
->
->
->
->
byte,
byte,
byte,
byte,
byte,
byte,
char
char
short
short,
short,
short,
short,
char
char, int
char, int, long
char, int, long, float
Gianpaolo Cugola
53
I costrutti OO per la programmazione “in
the large”
•
•
•
•
•
Classi
Interfaccie
Ereditarietà
Polimorfismo e binding dinamico
Packages
Gianpaolo Cugola
Gianpaolo Cugola
54
Definizione di una nuova classe
• Una nuova classe viene definita nel seguente
modo:
class <nome classe> {
<lista di definizioni di attributi e metodi>
}
• Esempio:
class Automobile {
...
}
Gianpaolo Cugola
55
Definizione di attributi
• Gli attributi di una classe definiscono la struttura dello
stato degli oggetti che vi appartengono
• Ogni attributo è definito usando la stessa sintassi usata
per la definizione delle variabili locali
• Esempio
class Automobile {
String colore, marca, modello;
int cilindrata, numPorte;
boolean accesa;
}
Gianpaolo Cugola
Gianpaolo Cugola
56
Definizione di metodi
• I metodi di una classe definiscono il comportamento
degli oggetti che vi appartengono
• Ogni metodo è definito come segue:
<tipo val. rit.> <nome.>([<dic. par. formali>])
<corpo>
• Il tipo void viene utilizzato per metodi che non
ritornano alcun valore
Gianpaolo Cugola
57
Definizione di metodi: esempio
class Automobile {
String colore, marca, modello;
int cilindrata, numPorte;
boolean accesa;
void accendi() {accesa=true;}
boolean puoPartire() {return accesa;}
void dipingi(String col) {colore=col;}
void trasforma(String ma, String mo) {
marca=ma;
modello=mo;
}
}
Gianpaolo Cugola
Gianpaolo Cugola
58
Visibilità dei nomi
• I nomi degli attributi e dei metodi sono visibili all’interno
di tutta la classe
• Le variabili dichiarate in un blocco sono visibili solo
all’interno del blocco
• Le variabili locali ad un metodo (o i parametri formali)
possono mascherare gli attributi
• Le variabili dichiarate all’interno di un blocco possono
mascherare le variabili dichiarate all’interno di blocchi più
esterni
Gianpaolo Cugola
59
Oggetti
• Ogni variabile il cui tipo sia una classe (o un interfaccia)
contiene un riferimento ad un oggetto
• Nuovi oggetti sono costruiti usando l’operatore new
• Esempio:
Automobile a=new Automobile();
• Ad una variabile di tipo riferimento può essere assegnato
il riferimento null
Gianpaolo Cugola
Gianpaolo Cugola
60
Accesso ad attributi e metodi di un
oggetto
• L’accesso ad attributi e metodi di un oggetto per
il quale si abbia un riferimento si effettua tramite
la “notazione punto”
• Esempio:
Automobile a=new Automobile();
a.accendi();
a.dipingi(“Blu”);
System.out.println(“Num. porte: “+a.numPorte);
Gianpaolo Cugola
61
Accesso ad attributi e metodi di un
oggetto da metodi dello stesso oggetto
• Nella definizione di un metodo ci si riferisce ad attributi e metodi
dell’oggetto sul quale il metodo sia stato invocato direttamente
(senza notazione punto)
• Esempio
class Automobile {
...
boolean puoPartire() {return accesa;}
void dipingi(String col) {colore=col;}
...
}
• La pseudo-variabile this contiene un riferimento all’oggetto
corrente e può essere utilizzata per aggirare eventuali
mascheramenti
Gianpaolo Cugola
Gianpaolo Cugola
62
La pseudo-variabile this: esempio
class Automobile {
String colore, marca, modello;
int cilindrata, numPorte;
boolean accesa;
void accendi() {accesa=true;}
boolean puoPartire() {return accesa;}
void dipingi(String col) {this.colore=col;}
void trasforma(String marca, String modello) {
this.marca=marca;
this.modello=modello;
}
}
Gianpaolo Cugola
63
Classi: esercizio
• Si definisca l’insieme di classi necessarie per
descrivere un computer (Monitor, Tastiera,
Mouse, Case, Scheda)
Gianpaolo Cugola
Gianpaolo Cugola
64
Passaggio parametri
• I parametri il cui tipo sia uno dei tipi semplici
sono passati per copia
• I parametri il cui tipo sia un tipo riferimento
(classi, interfacce e array) sono passati per copia
del riferimento
– ovvero, gli oggetti sono passati per riferimento
Gianpaolo Cugola
65
Overloading
• All’interno di una stessa classe possono esservi più
metodi con lo stesso nome purché si distinguano per
numero e/ o tipo dei parametri
– Il tipo del valore di ritorno non basta a distinguere due metodi
• Esempio:
class C {
int f() {...}
int f(int x) {...} // corretto
void f(int x) {...} // errato
}
Gianpaolo Cugola
Gianpaolo Cugola
66
Creazione e distruzione di oggetti
• La creazione di un oggetto comporta due operazioni:
– l’allocazione della memoria necessaria a contenere l’oggetto e
– l’inizializzazione dello spazio allocato
Quest’ultima operazione è svolta dal costruttore
• A differenza del C+ + in Java non è necessario deallocare
esplicitamente gli oggetti creati con una operazione new.
Di ciò si occupa il garbage collector
Gianpaolo Cugola
67
Costruttori
• Nella definizione di una classe è possibile specificare uno
o più costruttori
• Il costruttore è un metodo particolare che ha lo stesso
nome della classe
– Nel caso ci siano più costruttori, essi si distinguono perché
differiscono per numero e/ o tipo dei parametri
– Per i costruttori non viene indicato il tipo del risultato (è
implicito nel nome del costruttore)
• Il costruttore di default (senza parametri) viene fornito
dal compilatore a meno che non si definiscano altri
costruttori
Gianpaolo Cugola
Gianpaolo Cugola
68
Costruttori: esempio
class Automobile {
String colore, marca, mod ello;
int cilindrata, numPorte;
boolean accesa;
Automobile() {
colore=marca=modello= null;
cilindrata=numPorte=0;
}
Automobile(String colore, String marca, String modello) {
this.colore=colore; this.marca=marca;
this.modello=modello;
}
void accendi() {accesa= true;}
boolean puoPartire () {return accesa;}
void dipingi(String col) {this.colore=col;}
}
Gianpaolo Cugola
69
Ancora sui costruttori
• È possibile invocare un costruttore dall’interno di
un altro tramite la notazione:
this(<elenco di parametri attuali>);
• Esempio:
class Persona {
String nome;
int eta;
Persona(String nome) {this.nome=nome; eta=0;}
Persona(String nome, int eta) {
this(nome); this.eta=eta;
}
}
Gianpaolo Cugola
Gianpaolo Cugola
70
Classi e costruttori: esercizio
• Esercizio 1:
– Si costruisca una classe che implementa uno stack di interi di
dimensione fissa (stabilita in fase di costruzione)
• Esercizio 2:
– Si modifichi la classe precedente (introducendone altre se
necessario) per implementare uno stack di dimensione variabile
(allocazione dinamica di memoria)
• Esercizio 3:
– Si usi la classe precedente per realizzare un programma che
legge un file byte a byte e lo inverte
Gianpaolo Cugola
71
Metodi e attributi di classe
• Sintassi:
static <definizione dell’attributo o metodo>
• Un attributo di classe è condiviso da tutti gli oggetti della
classe
• Si può accedere ad un attributo di classe senza bisogno di
creare un oggetto tramite la notazione:
<nome classe>.<nome attributo>
• Un metodo di classe può essere invocato senza bisogno
di creare un oggetto tramite la notazione:
<nome classe>.<nome metodo>(<par. attuali>)
Gianpaolo Cugola
Gianpaolo Cugola
72
Metodi e attributi di classe: vincoli
• Un metodo static può accedere ai soli
attributi e metodi static
• Un metodo convenzionale può accedere
liberamente a metodi ed attributi static
Gianpaolo Cugola
73
Metodi e attributi di classe: esempio
class Shape {
static Screen screen=new Screen(); // si noti l’iniz.
static void setScreen(Screen s) {screen=s;}
void show(Screen s) {setScreen(s); ...}
}
...
Shape.setScreen(new Screen()); // corretto
Shape.show(); // errato, show è un metodo normale
Shape s1=newShape(), s2=new Shape();
Screen s=new Screen();
s1.setScreen(s); // corretto, si possono chiamare
// metodi static su oggetti
// in questo punto s2.screen==s1.screen==s
Gianpaolo Cugola
Gianpaolo Cugola
74
Attributi costanti
• È possibile definire attributi costanti tramite la notazione:
final <definizione di attributo>=<valore>
• Esempio
class Automobile {
int colore;
final int BLU=0, GIALLO=1,...;
void dipingi(int colore) {this.colore=colore;}
}
...
Automobile a=new Automobile();
a.BLU=128; // errato
System.out.println(“BLU=“+a.BLU); // corretto
Gianpaolo Cugola
75
Esercizio
• È corretto affermare che tramite attributi e
metodi di classe e attributi costanti è possibile
definire funzioni, variabili e costanti globali?
Gianpaolo Cugola
Gianpaolo Cugola
76
La gerarchia di ereditarietà
• Le classi di un sistema OO sono legate in una gerarchia
di ereditarietà
• Data una classe C, una sottoclasse di C si definisce
tramite la notazione:
class K extends C {
<definiz. di attr. e metodi>
}
• La sottoclasse eredita tutti gli attributi ed i metodi della
sopraclasse
• Java supporta solo ereditarietà semplice
Gianpaolo Cugola
77
La classe Object
• In mancanza di una differente indicazione, una
classe Java estende la classe Object
• La classe Object fornisce alcuni metodi tra i
quali vale la pena citare i seguenti:
public boolean equals(Object);
protected void finalize();
public String toString();
Gianpaolo Cugola
Gianpaolo Cugola
78
Overriding
• Una sottoclasse può aggiungere nuovi attributi e metodi
ma anche ...
• ridefinire i metodi delle sue sopraclassi
• Esempio:
class AutomobileElettrica extends Automobile {
boolean batterieCariche;
void ricarica() {batterieCariche=true;}
void accendi() {
if(batterieCariche) accesa=true;
else accesa=false;
}
}
Gianpaolo Cugola
79
La pseudo variabile super
• All’interno di un metodo che ridefinisce un metodo della
sopraclasse diretta ci si può riferire al metodo che si sta
ridefinendo tramite la notazione:
super.<nome metodo>(<lista par. attuali>)
• Esempio:
class AutomobileElettrica extends Automobile {
...
void accendi() {
if(batterieCariche) super.accendi();
else System.out.println(“Batterie scariche”);
}
}
Gianpaolo Cugola
Gianpaolo Cugola
80
Ereditarietà e costruttori
• I costruttori non vengono ereditati
• All’interno di un costruttore è possibile richiamare il
costruttore della sopraclasse tramite la notazione:
super(<lista di par. attuali>)
posta come prima istruzione del costruttore
• Se il programmatore non chiama esplicitamente un
costruttore della sopraclasse, il compilatore inserisce
automaticamente il codice che invoca il costruttore di
default della sopraclasse
Gianpaolo Cugola
81
Ereditarietà: esercizio
• Si definisca una classe Persona e due
sottoclassi Uomo e Donna. La classe Persona
deve avere un metodo chiSei() che stampa il
nome della persona. Nelle sottoclassi tale metodo
deve essere ridefinito perché stampi anche il sesso
Gianpaolo Cugola
Gianpaolo Cugola
82
Information hiding in Java
• Attributi e metodi di una classe possono essere:
– pubblic
• sono visibili a tutti
• vengono ereditati
– protected
• sono visibili solo alle sottoclassi
• vengono ereditati
– private
• sono visibili solo all’interno della stessa classe
• non sono visibili nelle sottoclassi
Gianpaolo Cugola
83
Information hiding: esempio
class Automobile {
private String colore, marca, modello;
private int cilindrata, numPorte;
private boolean accesa;
public Automobile() {
colore=marca=modello=null;
cilindrata=numPorte=0;
}
public Automobile(String col, String ma, String mo)
{colore=col; marca=ma; modello=mo;}
public void accendi() {accesa=true;}
public boolean puoPartire() {return accesa;}
public void dipingi(String col) {colore=col;}
}
Gianpaolo Cugola
Gianpaolo Cugola
84
Information hiding: esercizio
• Si modifichi l’esercizio precedente introducendo
le dichiarazioni di visibilità per i membri delle
classi
Gianpaolo Cugola
85
Classi e metodi astratti
• Un metodo astratto è un metodo per il quale non
viene specificata alcuna implementazione
• Una classe è astratta se contiene almeno un
metodo astratto
• Non è possibile creare istanze di una classe
astratta
• Le classi astratte sono molto utili per introdurre
della astrazioni di alto livello
Gianpaolo Cugola
Gianpaolo Cugola
86
Classi e metodi astratti: esempio
abstract class Shape {
static Screen screen;
Shape(Screen s) {screen=s;}
abstract void show();
}
class Circle extends Shape {
void show() {
...
}
}
...
Shape s=new Shape(); // errato
Circle c=new Circle(); // corretto
Gianpaolo Cugola
87
Classi astratte: esercizio
• Nell’esercizio precedente si introduca una classe
astratta OggettoConNome, sopraclasse di
Persona
Gianpaolo Cugola
Gianpaolo Cugola
88
Classi e metodi final
• Se vogliamo impedire che sia possibile creare sottoclassi
di una certa classe la definiremo final
• Esempio:
final class C {...}
class C1 extends C // errato
• Similmente, se vogliamo impedire l’overriding di un
metodo dobbiamo definirlo final
• Esempio:
class C { final void f() {...} }
class C1 extends C {
void f() {...} // errato
}
Gianpaolo Cugola
89
Ereditarietà ed array
• Se X è una sopraclasse di Y allora l’array X[] è
“sopra-array” dell’array Y[]
– Lo stesso vale per gli array multidimensionali
• Tale scelta non è type safe
• Esempio:
void f(X[] ax) {
ax[0]=new X();
}
...
f(new Y[10]);
Gianpaolo Cugola
Gianpaolo Cugola
90
I limiti dell’ereditarietà semplice
• L’ereditarietà semplice non permette la
descrizione di numerose situazioni reali
• Esempio:
– Supponiamo di avere una classe Giocattolo ed
una classe Automobile. In assenza di ereditarietà
multipla non posso definire la classe
AutomobileGiocattolo
Gianpaolo Cugola
91
I problemi dell’ereditarietà multipla
• In presenza di ereditarietà multipla è possibile ereditare
due o più metodi con la stessa “signature” da più
sopraclassi. Ciò determina un conflitto tra
implementazioni diverse
K
C1
C2
f (int i) : int
f (int i) : int
f (int i) : int
C1
C2
C
C
Gianpaolo Cugola
Gianpaolo Cugola
92
Ereditarietà semplice vs. ereditarietà
multipla: la soluzione di Java
• Distinguere tra una gerarchia di ereditarietà
(semplice) ed una gerarchia di implementazione
(multipla) ...
• introducendo il costrutto delle interfacce
• In tal modo è possibile distinguere tra l’uso
dell’ereditarietà al fine di riutilizzare il codice e
l’uso al fine di descrivere una gerarchia di tipi
Gianpaolo Cugola
93
Interfacce
• Una interfaccia è una classe priva di attributi non
costanti ed i cui metodi sono tutti pubblici ed
astratti
• Sintassi:
interface <nome> {
<lista di definizione di metodi
privi di corpo>
}
Gianpaolo Cugola
Gianpaolo Cugola
94
Interfacce ed ereditarietà
• Una interfaccia può ereditare da una o più
interfacce
• Sintassi:
interface <nome> extends <nome1>,..,<nomen> {...}
• La gerarchia di ereditarietà tra interfacce definisce
una gerarchia di tipi
Gianpaolo Cugola
95
Interfacce: esercizio
• In che senso una interfaccia descrive un tipo
meglio di una classe?
Gianpaolo Cugola
Gianpaolo Cugola
96
La gerarchia di implementazione
• Una classe può implementare una o più interfacce
– se la classe non è astratta deve fornire una
implementazione per tutti i metodi presenti nelle
interfacce che implementa
– altrimenti la classe è astratta
• Sintassi:
class <nome> implements <nome1>,..,<nomen> {...}
Gianpaolo Cugola
97
Polimorfismo
• Polimorfismo è la capacità per un elemento
sintattico di riferirsi a elementi di diverso tipo
• In Java una variabile di un tipo riferimento T può
riferirsi ad un qualsiasi oggetto il cui tipo sia T o
un sottotipo di T
• Similmente un parametro formale di un tipo
riferimento T può riferirsi a parametri attuali il cui
tipo sia T o un sottotipo di T
Gianpaolo Cugola
Gianpaolo Cugola
98
Polimorfismo: esempio
class Automobile {...}
class AutomobileElettrica extends Automobile {...}
class Parcheggio {
private Automobile buf[];
private int nAuto;
public Parcheggio(int dim) {buf=new Automobile[dim];}
public void aggiungi(Automobile a) {buf[nAuto++]=a;}
}
...
Automobile a=new AutomobileElettrica();
Parcheggio p=new Parcheggio(100);
p.aggiungi(new AutomobileElettrica());
Gianpaolo Cugola
99
Polimorfismo ed interfacce
• Una interfaccia può essere utilizzata come tipo di una
variabile
• Una siffatta variabile potrà riferirsi ad un qualsiasi
oggetto che implementi l’interfaccia (polimorfismo)
• Esempio:
interface OggettoCheSpara {
spara();
}
class Pistola implements OggettoCheSpara {...}
OggettoCheSpara o=new Pistola();
o.spara();
Gianpaolo Cugola
Gianpaolo Cugola
100
Polimorfismo: tipo statico e tipo
dinamico
• In presenza di polimorfismo distinguiamo tra il
tipo statico ed il tipo dinamico di una variabile (o
di un parametro formale)
– La regola del polimorfismo prima enunciata obbliga il
tipo dinamico ad essere un sottotipo (proprio o meno)
del tipo dinamico
Gianpaolo Cugola
101
Polimorfismo e binding dinamico
• In Java, a fronte della invocazione
x.f(x1,...,xn), l’implementazione scelta
per il metodo f dipende dal tipo dinamico di x e
non dal suo tipo statico
Gianpaolo Cugola
Gianpaolo Cugola
102
Binding dinamico: esempio
class Persona {
private String nome;
public Persona(String nome) {this.nome=nome;}
public void chiSei() {
System.out.println(“Ciao, io sono “+nome);
}
}
class Uomo extends Persona {
public Uomo(String nome) {super(nome);}
public void chiSei()
{super.chiSei(); System.out.println(“sono un maschio”);}
}
...
Persona p=new Uomo(“Giovanni”); p.chiSei();
OUTPUT:
Ciao, io sono Giov anni
sono un maschio
Gianpaolo Cugola
103
Polimorfismo e binding dinamico:
esercizio
• Si costruisca uno stack di persone e lo si usi per
conservarvi tanto uomini quanto donne. Al
termine si verifichi l’effetto del binding dinamico
richiamando il metodo chiSei() su tutti gli
oggetti conservati
Gianpaolo Cugola
Gianpaolo Cugola
104
Conversioni forzate tra tipi riferimento:
casting
• È possibile forzare esplicitamente la conversione
da un tipo riferimento T ad un sottotipo T1
purché:
– Il tipo dinamico dell’espressione che convertiamo sia
un sottotipo di T1
• Esempio:
Object o=new AutomobileElettrica();
Automobile a=o; // errato, Object non è un
// sottotipo di Automobile
Automobile a=(Automobile) o; // corretto (casting)
Gianpaolo Cugola
105
Casting: esercizio
• Si spieghi perché il casting è fondamentale per
implementare contenitori generici (stack di
Object ecc.)
Gianpaolo Cugola
Gianpaolo Cugola
106
Package ed information hiding
• Package e visibilità degli attributi e dei metodi
– Attributi e metodi di una classe C per i quali non sia dichiarato alcun tipo di
visibilità sono visibili solo all’interno di classi che appartengano allo stesso
package di C
– Tale costrutto gioca un ruolo analogo alla dichiarazione di friendship in C++
• Package ed importazione di classi
– Un package contiene un insieme di classi pubbliche ed un insieme di classi
private
– Solo le classi pubbliche si possono importare in altri package
• Package e compilation unit
– Ogni compilation unit contiene classi appartenenti allo stesso package
– Una compilation unit contiene una sola classe pubblica (per default la prima)
ed eventualmente altre classi private
Gianpaolo Cugola
107
Il package java.lang
• Il package java.lang contiene classi di uso
molto frequente (String, Object, ecc.)
• Non è necessario importare le classi appartenenti
al package java.lang prima di utilizzarle
Gianpaolo Cugola
Gianpaolo Cugola
108