Parte II: classi e oggetti
!
Metodi
!
Classi e oggetti
µ
Generalità
µ
Classi particolari predefinite:
• Stringhe
• Array
µ
Tipi riferimento
• Copia di oggetti e array
• Confronto tra oggetti e array
!
Package
!
Programmazione a oggetti in Java
!
Struttura generale di un file Java
!
Eccezioni
1: Introduction
1
Metodi
! Metodo: sequenza di istruzioni Java dotata di
nome (equivalente a una funzione in C)
! Può essere invocato da altro codice Java,
passandogli 0 o più argomenti, come una
chiamata a funzione
! Restituisce un valore (eventualmente void)
! Ogni metodo è definito all’interno di una
classe
! Nota: il passaggio dei parametri avviene per
valore
1: Introduction
2
Metodi/2
!
Firma (signature) del metodo:
<modificatore> <tipo> <nome> (<lista
parametri>) [throws <eccezioni>]
!
Modificatori:
µ
Accesso: public, private.
protected, package
µ
static
µ
final
!
Lista parametri: significato
analogo a C/C++
!
Tipi di eccezione che il metodo
può lanciare (opzionale)
!
Sono possibili più metodi con
lo stesso nome overloading
!
Corpo del metodo: sequenza di
istruzioni racchiuse tra
parentesi graffe
1: Introduction
3
Classi
! Struttura dotata di nome che
implementa un tipo di dato
! Contiene variabili e costanti (di classe) e
metodi
! Variabili di classe e metodi sono detti
membri della classe
! Più di 1500 classi predefinite in Java,
organizzate in package
1: Introduction
4
Classi, istanze, oggetti
Nel seguito:
!
Oggetti (istanze di classe)
!
Come istanziare classi già esistenti
!
Due importanti classi Java:
!
!
µ
String
µ
Array
Tipi per riferimento (dove si nascondono i puntatori)
µ
Copia di oggetti e array
µ
Confronto tra oggetti e array
Package
1: Introduction
5
Oggetti e istanze
!
!
Oggetto: valore di un
tipo di dato classe
!
!
Dichiarazione:
Point p;
!
!
Definisce una nuova
variabile p di tipo
Point, dove Point è
una classe
La lista di parametri è
opzionale
!
Point p = new Point(2,5) va
bene
!
Inizializzazione:
<identificatore> = new
<nome classe> (<lista
parametri>)
Inizializzazione:
La sola dichiarazione
non crea l’oggetto!!
new serve a invocare il
costruttore della classe,
come vedremo più avanti
!
p = new Point(2,5);
!
Sintassi simile a C++
!
Nota: la lista dei parametri
è opzionale (dipende dal
costruttore), le parentesi
1: Introduction
tonde sono necessarie
6
La classe primoEsempio
import java.io.*;
public class primoEsempio {
public static void main(String args[]) {
String nomeCorso, nomeDocente; /* Variabile locale (di metodo) */
docente docenteReti;
docenteReti = new docente();
nomeCorso = docenteReti.insegnamentoDocente();
nomeDocente = docenteReti.nomeDocente();
System.out.println("Nome del corso: " + nomeCorso);
System.out.println("Nome del docente: " + nomeDocente);
}
} /* Fine classe primoEsempio */
class docente { /* Non può essere pubblica */
private String nomeDocente = "Luca Becchetti"; /* Variabile di classe */
private String corsoDocente = "Reti di Calcolatori";
public String nomeDocente() {
return nomeDocente;
}
public String insegnamentoDocente() {
1: Introduction
7
return corsoDocente;
}
} /* Fine classe docente */
Classe String
!
!
Rappresenta stringhe
µ
Classe predefinita
µ
Mette a disposizione vari metodi utili (controllarli!!)
µ
Gli oggetti di questa classe rappresentano stringhe non
modificabili
L’inizializzazione ammette anche la sintassi seguente:
String nome = “Pippo”; /* String nome = new String(“Pippo”); */
!
Molti metodi utili:
µ
nome.length() restituisce la lunghezza (No. caratteri) della stringa
contenuta nell oggetto nome
µ
Molti metodi consentono di manipolare stringhe
µ
Consiglio: studiare la documentazione sulla classe (ci si può
arrivare dal Tutorial)
µ
Vedere anche la classe StringBuffer (come String, ma consente
1: Introduction
di rappresentare stringhe variabili)
8
Array
!
Lista indicizzata di valori dello stesso tipo
!
Valori appartenenti a:
!
µ
Tipi primitivi
µ
Tipi riferimento (Oggetti, stringhe, array)
Dichiarazione di array:
!"#$%%%!&%
)+(,(#(-*
!"#$./%%%%%%%0++0"12(1!"#$&%
%
!"#$././%%%%0++0"12(1%0++0"12(1!"#$&%
3*(4#./% % % % % 0++0"12(13*(4#&%
%
56077$%3*(4#
!
%''%#()*
%
%''%#()*%0++0"
%''%#()*%0++0"
% ''% #()*% 2(
Sintassi alternativa (tipo C/C++):
3*(4#%%%%%0++0"12(13*(4#./&
Attenzione: la dichiarazione non alloca memoria per l’array!!
1: Introduction
9
Array/2
!
Creazione di array:
µ
!
!
Si può usare l’operatore new con questa sintassi:
String[] lines = new String[50]; /* Crea un array di 50 stringhe */
/* Attenzione: alloca la memoria per contenere 50 riferimenti a oggetti di classe
String!! */
L’array creato ha dimensione fissa (es.: 50 oggetti di
tipo String nell’esempio precedente)
Dopo la creazione, le componenti dell’array sono
inizializzate a valori di default che dipendono dal tipo
base
µ
false per boolean
µ
0 per int
µ
0.0 per float
µ
null per oggetti
1: Introduction
10
Array/3
Creazione e inizializzazione:
!
int[] multipli_di_due = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
Viene creato un array di 10 interi. Si può usare la stessa
sintassi con oggetti
!
multipli_di_due[2] restituisce 6 (gli iniziano da 0, come in
C)
!
La lunghezza di un array è definita con la sua creazione
e ne è una proprietà intrinseca.
!
Se:
String[] lines = new String[50];
Allora lines.length restituisce 50
!
!
.length non è un metodo -> niente parentesi tonde!!
!
Può essere usato soltanto con gli array!!
1: Introduction
11
Array multidimensionali
!
Per creare un array multidimensionale occorre specificare
almeno la dimensione più a sinistra
!
Se si specificano più dimensioni, devono essere quelle più a
sinistra
int[][][] matrice3D = new int[10][20][30]; // GIUSTO
int[][][] matrice3D = new int[10][][];
// GIUSTO
int[][][] matrice3D = new int[10][20][]; // GIUSTO
int[][][] matrice3D = new int[][20][30]; // SBAGLIATO !!!
int[][][] matrice3D = new int[10][][30]; // SBAGLIATO !!!
!
Creazione e inizializzazione esplicita
di array
(senza new):
int[][] matrice2D
= { {0,0},
int[][] matrice2D = { {0,0,0,0,0},
{0,1,2,3,4},
{0,2,4,6,8},
{0,3,6,9,12} };
{0,1,2,},
{0,2,4,6,8},
{0,3,6,9,12} };
1: Introduction
12
Tipi per riferimento
Tutti i tipi primitivi hanno dimensione (in byte)
determinata e sono manipolati direttamente
!
Array, stringhe e, in generale oggetti, non sono
manipolati direttamente, ma attraverso puntatori
!
Una variabile avente per tipo una classe (array,
stringa) contiene in realtà un riferimento (puntatore)
all’ oggetto (array, stringa)
!
Se:
!
Point p = new Point(2, 5);
Allora p contiene un riferimento al nuovo oggetto di
1: Introduction
classe Point creato
13
Tipi per riferimento/2
!
I riferimenti sono simili ai puntatori C/C++ ma non possono
essere manipolati
!
Conseguenze cui prestare attenzione:
! Copia tra variabili di tipo primitivo:
int x = 42;
int y = x;
Alla fine sia x che y contengono il valore 42
! Copia di oggetti:
Point p = new Point(1,2);
Point q = p;
q e p contengono lo stesso riferimento e quindi puntano allo
stesso oggetto!!
Modificare q (ad esempio q.x = 3) significa modificare
1: Introduction
l’oggetto originale
14
Tipi per riferimento/3
!
Per copiare array: si usa il metodo arraycopy()
public class ArrayCopyDemo {
public static void main(String[] args) {
char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e',
'i', 'n', 'a', 't', 'e', 'd' };
char[] copyTo = new char[7];
System.arraycopy(copyFrom, 2, copyTo, 0, 7);
System.out.println(new String(copyTo));
}
}
!
Per copiare stringhe basta usare il costruttore:
String Stringa1 = “Io sono una copia”;
String Stringa2 = new String(Stringa1);
1: Introduction
15
Tipi per riferimento/4
!
Per copiare oggetti si può usare il metodo clone(), ereditato
dalla classe Object (vale anche per array e stringhe):
int[] data = {1,2,3,4,5};
int[] copy = (int[]) data.clone();
Attenzione al cast!!
!
!
!
L’oggetto può essere clonato solamente se la classe cui
appartiene implementa l’interfaccia Cloneable (più avanti nel
corso)
Il clone di un oggetto contiene una copia di ogni valore primitivo
e di ogni riferimento -> clone() non è ricorsivo
Per copiare oggetti si possono anche copiare i singoli campi, uno
a uno -> Attenzione ai riferimenti!!
1: Introduction
16
Tipi per riferimento/5
!
Confronto tra stringhe:
String a = new String(“ciao”);
String b = new String(“ciao”);
!
!
a == b in generale restituisce false
Bisogna usare il metodo equals(), ereditato dalla
classe Object:
if (a.equals(b))
System.out.println(“Vero!!”);
!
Viene stampato Vero!!
1: Introduction
17
Package
!
!
Collezione di classi dotata di nome (può contenere
subpackage)
java.lang è il package fondamentale del linguaggio
Java. Contiene le classi principali, tra cui Object,
String, ecc
!
Tutte le classi del package c possono indicare classi
dello stesso package usando solamente il nome
!
Importando un package si possono usare i nomi
abbreviati per le classi del package. Es.:
import java.util.*;
…….
Hashtable h = new Hashtable(); Altrimenti:
java.util.Hashtable h = new java.util.Hashtable();
1: Introduction
18
Struttura generale di un file .java
!
1 direttiva opzionale package
!
0 o più direttive import
!
!
!
package mypackage; /* Specifica che questa
classe appartiene a mypackage */
Una o più classi, di cui una
sola pubblica
import java.util.*;
import java.io.*;
Dopo la compilazione a
ciascuna classe corrisponde
un file .class separato,
contenente il byte code
public class classePrincipale {
…..
}
class secondaClasse {
….
}
class terzaClasse {
….
}
…….
Nome del file: classePrincipale.java
Il nome del file deve essere
quello della classe pubblica
(estensione .java)
1: Introduction
19
Programmazione a oggetti in Java
!
!
!
!
Membri di una classe
µ
Campi statici e istanza
µ
Metodi statici e istanza
Creazione e inizializzazione di oggetti - costruttori
Distruzione e finalizzazione di oggetti – garbage
collection
Sottoclassi e ereditarietà
µ
Classi final
µ
Gerarchia delle classi
µ
Shadowing
µ
Overloading
µ
Overriding
1: Introduction
20
Classe
! Struttura dotata di nome che
implementa un tipo di dato
! Contiene variabili e costanti (di classe) e
metodi
! Variabili di classe e metodi sono detti
membri della classe
1: Introduction
21
1: Introduction
22
Struttura di una classe
!
Campi (variabili di
classe)
!
Metodi
!
Campi/metodi statici:
µ
µ
Appartengono alla classe e
non a un oggetto
particolare
Sono identificati dal
modificatore static
Struttura di una classe
public class Circle {
public static final double PI = 3.14159; // Campo statico (in questo caso una costante)
public double r;
// Campo istanza: il raggio di un cerchio
public static double radiansToDegrees(double rads) { // Passa da radianti a gradi
return rads*180/PI;
}
public double area() // Metodo istanza: calcola l’area di un cerchio
{
return PI*r*r;
}
public double circumference() // Metodo istanza: calcola la circonferenza di un cerchio
{
return 2*PI*r;
}
} /* Fine della classe */
1: Introduction
23
Membri di una classe
!
Modificatori di accesso: determinano la visibilità di membri di
una classe
µ
private double r; /* Nella classe Circle */: solo oggetti della classe
Circle possono accedere al campo r
µ
private double area() { /* Nella classe Circle */
return r*r*PI;
}
Solo oggetti della classe Circle possono accedere al metodo area()
µ
public: tutti gli oggetti, di qualunque classe, in qualunque package,
possono accedere al campo/metodo
µ
protected: solamente oggetti di sottoclassi o classi appartenenti
allo stesso package della classe possono accedere al campo/metodo
µ
package: solamente classi dello stesso package possono accedere al
campo/metodo
24
1: Introduction
Membri di una classe/2
!
Un campo/metodo istanza è privo del modificatore static.
Appartiene all’istanza e non alla classe
!
Campi:
µ
public double r; /* Nella classe Circle */
Ogni istanza della classe Circle possiede il proprio valore di r
µ
Se:
µ
Circle myCircle = new Circle();
µ
Allora myCircle.r permette di accedere al valore del campo r di
myCircle da altre classi (all’interno della classe Circle basta r)
Metodi:
Circle myCircle = new Circle();
myCircle.area() permette di accedere al metodo area() dell’oggetto
da altri oggetti. area() può essere usato all’interno della classe
in modo equivalente a this.area()
!
1: Introduction
25
Membri di una classe/3
!
!
!
!
Un campo statico è essenzialmente una variabile globale alla
classe
Qualunque oggetto di classe Circle ha la stessa copia della
variabile PI
PI può essere usata senza definire oggetti di classe Circle
Bisogna usare Circle.PI da oggetti non appartenenti alla classe
Circle, mentre si può usare PI da oggetti di classe PI:
myClass myObject = new myClass();
Circle myCircle = new Circle();
myObject.a = PI; /* Sbagliato !! */
myObject.b = myCircle.PI: /*Corretto!! Anche: Circle.PI */
!
Attenzione: i campi statici sono inizializzati una volta sola, dal
primo oggetto della classe creato
1: Introduction
26
Membri di una classe/4
!
Un metodo statico è associato alla classe, non a una
particolare istanza
!
Può essere usato senza creare un oggetto della
classe:
double d = Circle.radiansToDegrees(2.0);
!
!
!
Un metodo statico può usare qualsiasi campo o
metodo statico definito nella propria classe o in
un’altra
Un metodo statico non può usare campi o metodi
istanza
La classe java.lang.Math mette a disposizione metodi
statici per le principali funzioni matematiche
27
1: Introduction
Membri di una classe/5
class AnIntegerNamedX {
int x;
static public int x() {
return x;
}
static public void setX(int newX) {
x = newX;
}
}
Errore: setX() è statico ma
accede a x (variabile istanza)
Modificatore static:
!
Variabili: serve a definire una
costante
!
!
static double PI = 3.14; definisce
una variabile di classe
Se l’oggetto circle esegue
l’istruzione:
PI = 0; il valore di PI è posto a 0
per tutti gli oggetti di classe
Circle
!
Modificatore final:
final double PI = 3.14; definisce una
costante PI per ogni istanza della
classe Circle
!
final static double PI = 3.14; definisce
una sola costante PI per ogni 28
1: Introduction
istanza della classe Circle
Creazione e inizializzazione di
oggetti
)8!6(5%56077%9(+56$%:
% % )8!6(5% 7#0#(5% ;(406% 2*8!6$% 3<% =% >?@A@BC&
'D%90,)*%7#0#(5*!D'
%%)8!6(5%2*8!6$%+&
Costruttore:
!
'D%90,)*%(7#04E0%D'
% % )8!6(5% 9(+56$F2*8!6$% +0GG(*H% :% 'D
9IJKLMKKILN%D'
%'D%<4(E(06(EE0%(6%50,)*%(7#04E0%+%D'
+% =% +0GG(*&% 'D% O45P$Q% #P(7?+% =% +0GG(*&
D'
%%R
!% )8!6(5% 2*8!6$% 0+$0FH% % % % % :% 'D% S$#*2*
(7#04E0%D'
%%%%+$#8+4%3<D+D+&
%%R
)8!6(5% 2*8!6$% 5(+58,;$+$45$FH% :'D
S$#*2*%(7#04E0%D'
+$#8+4%TD3<D+&
%%R
R%'D%U(4$%2$660%56077$%D'
Stesso nome della classe, senza
tipo, perché un costruttore non
ha valori di ritorno, neppure void
!
Se non definito -> costruttore di
default
!
Il costruttore ha il compito di
inizializzare l’oggetto this
!
!
E’ possibile avere costruttori
multipli, purché abbiano liste dei
parametri diverse (overloading)
Modificatori di accesso (private,
public, protected, package):
permettono di specificare quali
oggetti possono creare istanze
della classe
1: Introduction
29
Distruzione e finalizzazione di
oggetti
!
!
!
!
Garbage collection: quando un oggetto non è più
usato (non esistono riferimenti ad esso) la sua
memoria può essere liberata
Finalizzazione: prima della garbage collection, la
JVM invoca il metodo finalize() (valore restituito
void) di un oggetto (ereditato da java.lang.Object).
Se una classe implementa finalize(), allora le azioni
previste nel metodo sono eseguite prima della
garbage collection
Nessuna garanzia sull’istante di invocazione di
finalize()
1: Introduction
30
Sottoclassi e ereditarietà
)8!6(5%56077%9(+56$%:
% % )8!6(5% 7#0#(5% ;(406% 2*8!6$% 3<% =% >?@A@BC&% % 'D
90,)*%7#0#(5*!D'
%%)8!6(5%2*8!6$%+&
'D%90,)*%(7#04E0%D'
%%)+(-0#$%(4#%48,!$+I;9(+56$7&%%'D%3+(-0#*VVD'
%%)8!6(5%9(+56$FH%:%'D9IJKLMKKILN%D'
%%
+=@&
%%R
% %)8!6(5%9(+56$F2*8!6$% +0GG(*H% :% 'D% 9IJKLMKKILN
D'
%'D%<4(E(06(EE0%(6%50,)*%(7#04E0%+%D'
+%=%+0GG(*&%'D%O45P$Q%#P(7?+%=%+0GG(*&%D'
%%R
!%)8!6(5%2*8!6$%0+$0FH%%%%%:%'D%S$#*2*%(7#04E0%D'
%%%%+$#8+4%3<D+D+&
%%R
)8!6(5% 2*8!6$% 5(+58,;$+$45$FH% :'D% S$#*2*
(7#04E0%D'
+$#8+4%TD3<D+&
%%R
R%'D%U(4$%2$660%56077$%9(+56$%D'
public class planeCircle extends Circle {
public double cx, cy;
public planeCircle(double x, double y) { /*
COSTRUTTORE */
/* Implicitamente: super(); */
cx = x; /* this.cy = y; */
cy = y; /* this.cy = y; */
}
public static void main(String args[]) {
Circle myCircle = new Circle(2.0);
System.out.println(myCircle.area());
System.out.println(myCircle.circumference());
/* System.out.println(myCircle.numberOfCircles); Sbagliata
perché numberOfCircles è privata alla classe Circle */
System.out.println(myCircle.r);
planeCircle myPlaneCircle = new
planeCircle(0.0, 0.0);
/* System.out.println(myPlaneCircle.numberOfCircles);
sbagliata perché numberOfCircles non è ereditata */
System.out.println(myPlaneCircle.r);
System.out.println(myPlaneCircle.area());
System.out.println(myPlaneCircle.circumference());
}
}
1: Introduction
31
Sottoclassi e ereditarietà/2
Cosa si eredita:
!
Tutti i campi/metodi dichiarati public o protected
!
Tutti i campi/metodi privi di modificatore di accesso, purché la
sottoclasse appartenga allo stesso package della superclasse
Cosa non si eredita:
!
Membri dichiarati private
Costruttori. Es.:
PlaneCircle myPlaneCircle = new PlaneCircle(3.0);
Sbagliato, perché PlaneCircle non eredita il costruttore di Circle
!
!
Membri privi di modificatore di accesso, qualora la sottoclasse
non appartenga allo stesso package della superclasse
!
Variabili con lo stesso nome di variabili della sottoclasse
(shadowing)
!
Metodi con lo stesso nome di metodi della sottoclasse
(overriding)
1: Introduction
32
Sottoclassi e ereditarietà /3
public PlaneCircle(double r, double x, double y) {
super(r);
this.cx = x;
this.cy = y;
}
!
Il costruttore della
sottoclasse usa quello
della superclasse
!
Prima istruzione:
invocazione di un
costruttore della
superclasse
!
!
!
!
!
La prima istruzione del
costruttore di una
sottoclasse deve sempre
essere la chiamata di un
costruttore della superclasse
Se ciò non accade, il
compilatore inserisce
implicitamente una chiamata
a super()
Se non esiste un costruttore
della superclasse che non
accetta argomenti -> errore
super indica la superclasse
super() permette di
specificare un costruttore
1: Introduction
della superclasse
33
Sottoclassi e ereditarietà/4
I!W$5#
9(+56$
3604$9(+56$
S0#P
J"7#$,
Object:
!
Unica classe che non
ha superclasse
!
Ogni classe eredita i
metodi di Object
Classi final:
!
L$02$+
<4)8#J#+$0,L$02$+
U(6$L$02$+
U(6#$+L$02$+
J#+(4GL$02$+
Non ammettono
sottoclassi
In figura: Sottoinsieme
delle classi Java
1: Introduction
34
Sottoclassi e ereditarietà /5
Field Shadowing (Nascondere campi)
C è sottoclasse di B che è sottoclasse di
A. Tutte e tre le classi hanno un
campo x. Siamo in C:
Method overriding (ridefinizione)
!
X%%%%%%%%%%%%%%%%%%''%90,)*%X%2(%9
#P(7?X%%%%%%%%%%%%''%90,)*%X%2(%9
78)$+?X%%%%%%%%%%%''%90,)*%X%2(%Y
FFYH#P(7H?X%%%%%%%''%90,)*%X%2(%Y
FFOH#P(7H?X%%%%%%%''%90,)*%X%2(%O
78)$+?78)$+?X% % % % % ''% JYOZ[<OKIQ% 4*4% 7(
+(;$+(75$%06%50,)*%X%2(%O
La variabile della
sottoclasse nasconde quella
della superclasse con lo
stesso nome
!
La sottoclasse definisce un
metodo con gli stessi nome,
lista parametri e tipo
class A {
int i = 1;
int f() {return i;}
}
class B extends A {
int i; // Questo campo nasconde il campo i di A
int f() // Questo metodo ridefinisce il metodo f() di
A
{
i = super.i + 1;
// super.i è il campo i di A,
ovvero A.i
return super.f() + i; // super.f() è il metodo f() di
A, ovvero A.f()
}
}
35
1: Introduction
Sottoclassi e ereditarietà /6
class A {
int i = 1;
int f() {return i;}
}
public class eredi2 extends A {
int i;
/* Questo campo nasconde il campo i di A */
int f() { /* Questo metodo ridefinisce il metodo f() di A */
i = super.i + 1;
/* super.i è il campo i di A, ovvero A.I */
System.out.println(super.i); /* Stampa 1 */
System.out.println(super.f()); /* Stampa 1 */
System.out.println(i); /* Stampa 2 */
return super.f() + i; /* super.f() è il metodo f() di A, ovvero A.f() */
}
public static void main(String args[]) {
eredi2 myB;
myB = new eredi2();
System.out.println(myB.i); /* Stampa 0 */
System.out.println(myB.f()); /* Stampa 3 */
}
}
1: Introduction
36
Ricapitolando….
!
!
!
!
!
!
Method Overloading: definizione, nella stessa classe, di
metodi/costruttori con lo stesso nome e firma diversa
Field Shadowing: variabili della sottoclasse nascondono variabili
della superclasse con lo stesso nome
Method Overriding: ridefinizione nella sottoclasse di un
metodo della superclasse con stesso nome, tipo restituito e
lista dei parametri
Attenzione a non confondere super() con super.f()
I metodi static possono soltanto essere nascosti da metodi
static con la stessa firma
Metodi final: per definizione, un metodo final non può essere
ridefinito
1: Introduction
37
Classi astratte
Metodo astratto: prototipo, dichiarato con il modificatore
abstract. Es.:
public abstract void myMethod(String name);
! Classe astratta: ogni classe contenente almeno un metodo
astratto
!
!
Una classe astratta non può essere istanziata
!
Per usare una classe astratta, è necessario definirne una
sottoclasse che ne implementi tutti i metodi astratti
!
Una classe astratta può contenere dichiarazioni di variabili e
abstract
class myClass
{
metodi
non astratti
int x;
.....
public abstract void mymethod(int val);
.........
}
1: Introduction
38
Interfacce
!
Blocco di dichiarazioni di metodi, preceduta dalla parola chiave
interface. Rende superflua l’ereditarietà multipla
public interface myInterface {
void firstMethod(String name);
void secondMethod();
int thirdMethod(int val);
}
!
Una classe implementa l’interfaccia se ne implmenta tutti i
metodi
abstract class myClass implements myInterface {
int x;
public abstract void firstMethod(String name){
System.out.println(name);
}
/* Altri metodi, tra cui secondMethod() e thirdMethod() */
}
1: Introduction
39
Interfacce/2
public interface generalCircle {
double area();
double circumference();
}
!
Le classi Circle e myCircle implementano l’interfaccia
!
Bisogna indicarlo esplicitamente:
public class planeCircle extends Circle implements generalCircle {
.....
}
Esempio: Object implementa il metodo clone() ma non l’interfaccia
Cloneable (nel senso che non lo indica esplicitamente)
!
Si possono avere sottointerfacce
1: Introduction
40
Eccezioni
!
!
Eccezione: “An event during
program execution that
prevents the program from
continuing normally;
generally, an error” (Tutorial)
Java mette a disposizione
meccanismi per la gestione
delle eccezioni:
µ
µ
Unità 1
Unità 2
try {
.......
}
catch{....}
.......
...throws
Un meccanismo che
permette a unità di
programma di segnalare
eccezioni (istruzione throw)
Un costrutto che permette a
unità di programma di
gestire eccezioni segnalate
da altre unità di programma
(costrutto try-catch-finally)
1: Introduction
41
Eccezioni/2
!
!
Implementate come oggetti, istanze della classe (o di una
sottoclasse di) java.lang.Throwable
java.lang.Throwable ha due sottoclassi:
µ
µ
!
java.lang.Error: errori generalmente irrecuperabili
java.lang.Exception: errori meno gravi. Es.: tentativo di leggere un
file inesistente (FileNotFoundException), lettura oltre gli indici
iniziale o finale di un array (ArrayIndexOutOfBoundsException)
Un metodo può lanciare un’eccezione con l’istruzione:
throw <espressione>; il tipo di <espressione> deve essere quello dell’eccezione
che si vuole lanciare
!
Il costrutto try-catch identifica i blocchi di codice che possono
generare eccezioni e permette di definire blocchi di codice per
gestire diversi tipi di eccezione
1: Introduction
42
Eccezioni/3
!
!
!
!
Esistono numerose
sottoclassi di Exception
Unchecked exceptions: quelle
che sono sottoclassi di
java.lang.Error o
java.lang.RuntimeException
(ad esempio
IllegalArgumentException).
Non è obbligatorio gestirle
Checked exceptions: le altre.
Per esse occorre prevedere il
blocco try-catch, altrimenti
si ha errore di compilazione
Vedremo molti esempi di
eccezioni del secondo tipo
public class myMathClass {
public static double factorial(int x) {
if(x<0)
throw IllegalArgumentException(^x deve essere
>= 0_);
double fact;
for(fact = 1.0; x > 1; fact *= x, x--);
return fact;
}
}
/*In un’altra classe...*/
.........
int y;
.........
int fatt;
try { fatt = myMathClass.factorial(y);}
catch(IllegalArgumentException e) {
System.out.println(^Argomento errato_);
}
\\\.
43
1: Introduction
Eccezioni/4
!
Blocco catch:
µ
!
Si ha un blocco catch per
ogni tipo di eccezione che
viene gestito (non è detto
che siano tutte le
eccezioni possibili)
Blocco finally: è
opzionale e può servire a
eseguire azioni che
vanno comunque
compiute e/o a gestire il
caso in cui l’eccezione
non appartenga ad alcuno
dei tipi previsti nei
blocchi catch
try {
\ (qui 1 contenuto del codice che pu1 lanciare
un]eccezione)
}
catch(SomeException e1) {
\ (codice che gestisce un]eccezione di tipo
SomeException)
}
catch(AnotherException e2) {
\ (codice che gestisce un]eccezione di tipo
AnotherException)
}
finally {
\ (codice che viene sempre eseguito, dopo essere
usciti per qualsiasi motivo dal blocco try 1
tranne nel caso in cui venga invocato il metodo
System.exit(), che interrompe l]esecuzione
dell]interprete Java)
}
1: Introduction
44
Eccezioni/5
Se l’esecuzione di
<Istruzione 1> genera
un’eccezione, nessuna
delle istruzioni
successive è eseguita
!
Un blocco catch può non
gestire direttamente
un’eccezione, ma
lanciarla a sua volta
all’unità chiamante
!
try {
`<7#+8E(*4$%@a
`<7#+8E(*4$%Ta
???????????????????????????????????
}
catch(SomeException e1) {
\ (codice che gestisce un]eccezione di tipo
SomeException)
}
catch(AnotherException e2) {
#P+*b%4$b%O4*#P$+NX5$)#(*4FH&
'D%#P+*b%$T&%-0%045P$%!$4$%D'
}
catch(Exception e3) {
\ (simile alla clausola default del costrutto switch)
}
finally {
\ (codice che viene sempre eseguito)
}
1: Introduction
45
Eccezioni/6
Si possono definire nuove
eccezioni come sottoclassi
!
Sono di tipo checked se non
sottoclassi di eccezioni
unchecked
!
Attenzione: un metodo che
può lanciare un’ eccezione
unchecked deve segnalarlo
con la clausola throws
!
class myMathException extends Exception {
myMathException(String message) {
/*COSTRUTTORE */
super(message);
}
}
public class myMathClass {
public static double factorial(int x) throws
myMathException {
if(x<0)
throw
new
myMathException("x deve essere >= 0");
double fact;
for(fact = 1.0; x > 1; fact *= x, x--);
return fact;
}
public static void main(String args[]) throws
myMathException {
int x = -1;
try {
System.out.println(myMathClass.factorial(x));
}
catch (myMathException e) {
throw e;
}
}
}
46
1: Introduction
Ricapitolando….
!
Le eccezioni checked devono essere gestite
!
Se un metodo può generare un’eccezione checked deve
segnalarlo con la clausola throws
!
Un blocco catch può limitarsi a rilanciare un’eccezione
!
Se Exception2 è sottoclasse di Exception1 allora il blocco
catch relativo a Exception1 cattura anche eccezioni di tipo
Exception2
!
Si possono definire nuove eccezioni come sottoclassi di
eccezioni già definite
!
Se le nuove eccezioni non sono sottoclassi di
java.lang.RuntimeException allora sono di tipo checked
!
Molti metodi di classi predefinite possono lanciare eccezioni di
vario tipo
!
Utile nell’accesso alle risorse di sistema
1: Introduction
47