Sei sulla pagina 1di 148

Java

Il linguaggio Java
Denito dalla Sun Microsystems nel 1995/96
Useremo la versione J2SE (Java 2 Standard EdiAon) SenArete parlare anche di jdk e di jre AHenzione: no alla versione 1.4 alcuni costruM sintaMci non esistevano

Esistono anche J2EE (Java 2 Enterprise EdiAon)


costruita sopra J2SE, ore servlets e JSP, EJB per sviluppare applicazioni "server side"

J2ME (Java 2 Micro EdiAon)


per piccoli disposiAvi (telefoni, PDA,)

CaraHerisAche
Object-oriented (OO) Distribuito
RMI e altri strumenA di distribuzione

Indipendente dalla piaHaforma


Bytecode e Java Virtual Machine

Sicuro
Esecuzione in una "sandbox" che garanAsce che non si possa danneggiare l'host

Sorpresa!
Non esistono i "tradizionali" conceM di
"programma" "soHoprogramma" (funzione o procedura)

Esistono le classi, che raggruppano (tra le altre cose) daA privaA e metodi
i metodi sono il termine OO usato per i soHoprogrammi
hanno sintassi analoga alle funzioni C

Classi come astrazioni

La struHura di un programma Java


Un programma Java organizzato come un insieme di classi
Ogni classe corrisponde a una dichiarazione di Apo o a una collezione di funzioni Una classe conAene dichiarazioni di variabili (aHribuA) e di funzioni (metodi)

Il programma principale rappresentato da un metodo speciale di una classe, deHo main

Il primo programma Java


le: HelloWorld.java
public class HelloWorld { public static void main(String[] args){ System.out.println("Hello world!"); } }

Esempio di classe in Java


public class Data { private int giorno; private int mese; private int anno; // restituisce il giorno public int leggiGiorno(){} // restituisce il mese public int leggiMese(){} // restituisce lanno public int leggiAnno(){} }

Il costruHo class
Una classe pu essere vista come un Apo denito dall utente che specica le operazioni uAlizzabili sul Apo stesso Il Apo pu essere usato per dichiarare altre variabili
int a, b;
dichiara due variabili a e b sulle quali possibile fare tuHe le operazioni predenite per il Apo int dichiara una variabile d sulla quale possibile fare tuHe le operazioni denite nella classe Data

Data d;

Denisce un ADT

OggeM
TuM gli oggeM della stessa classe hanno la stessa struHura
Il numero e Apo dei loro aHribuA di istanza lo stesso Ad esempio, la classe Data denisce tuHe le date possibili, tramite gli aHribuA giorno, mese, anno

Ogni oggeHo, in ogni istante dell esecuzione del programma, caraHerizzato da uno stato, che dato dal valore degli aHribuA dell oggeHo
Lo stato dell oggeHo data1 di Apo Data denito dal valore degli aHribuA giorno, mese, anno

Accesso ad aHribuA e metodi


Tramite la "notazione punto" Esempio:
Data d; int x; //codice che inizializza d x = d.leggiGiorno();

Esegue leggiGiorno() su oggeHo d: resAtuisce valore del giorno della data d E come se leggiGiorno() avesse come argomento implicito d: in C scriveremmo: leggiGiorno(d); Si dice anche che all oggeHo d inviamo il messaggio leggiGiorno

CambiamenA di stato
Lo stato degli oggeM (mutabili) pu cambiare nel tempo, chiamando metodi opportuni
data1 Data
giorno = 30 mese = 12 anno = 2010 data1.giornoDopo()

data1 Data
giorno = 31 mese = 12 anno = 2010

Esistono alcuni casi in cui gli oggeM sono immutabili (cio non possono essere modicaA)
Ad es. la classe predenita String

metodo giornoDopo()
Per modicare lo stato, il metodo deve potere accedere ai campi delloggeHo su cui stato chiamato Nella denizione di un metodo ci si pu riferire direHamente (senza notazione punto) ad aHribuA e metodi delloggeHo sul quale il metodo sia stato invocato
public void giornoDopo() { giorno++; if (giorno > 31) { giorno = 1; mese++; } if (mese > 12) { mese = 1; anno++; } } Data d; d.giornoDopo(); //modifica lo stato

Private e public
AHraverso i metodi "public" di una classe possibile vedere qual lo stato di un oggeHo ...
Data d; int x; x = d.leggiGiorno();

ma non accedere ai daA "private" (al di fuori del codice di Data):


if (d.mese == 12) //Errore di compilazione!

Programmazione "in the small"

Tipi primiAvi e variabili


Tipi numerici:
byte: 8 bit short: 16 bit int: 32 bit long: 64 bit oat: 32 bit double: 64 bit

Dichiarazione
byte unByte; int a, b=3, c; char c= h , car; boolean trovato=false;

Altri Api:
boolean: true, false char: 16 bit, caraHere Unicode

Variabili e Api riferimento


Le variabili di Apo primiAvo (numerico, char, bool) contengono il valore TuHe le altre contengono riferimenA a valori (ecco perch si dicono essere "di Apo riferimento") I Api riferimento sono:
Tipi deniA dall utente (classi, interfacce) Tipi array Enumerazioni

Tipi riferimento possono essere uAlizzaA ovunque si usi un Apo: Le variabili

Dichiarazioni di variabili e parametri, Apo del valore resAtuito da un metodo Consentono di accedere agli oggeM Sono allocate nello stack a run-Ame quando si chiama il metodo in cui sono dichiarate Gli oggeM referenziaA dalle variabili sono invece allocaA sullo heap Sono deallocate quando il soHoprogramma ritorna al chiamante

Ancora su Apo riferimento


Ogni variabile dichiarata con una classe conAene un riferimento a un oggeHo: un indirizzo di memoria Un oggeHo memorizzato in una opportuna area di memoria
il valore eeMvo dellindirizzo non noto e non interessa d, di Apo Data, conAene l indirizzo della prima cella delloggeHo
d giorno mese anno

xxx

3 11 2010

Dichiarazione e inizializzazione
La dichiarazione di una variabile di Apo riferimento non alloca spazio per un oggeHo, ma solo per il riferimento ad un oggeHo A una variabile di Apo riferimento assegnato inizialmente il riferimento null, per indicare che la variabile non ancora associata ad alcun oggeHo
Data d;
d vale null, non esiste ancora un oggeHo di Apo Data

Un parametro o una variabile locale non possono essere usaA senza essere inizializzaA In entrambi i casi occorre costruire un oggeHo e inizializzarlo esplicitamente

Il compilatore rileva staAcamente mancanza di inizializzazione

New
La costruzione di un oggeHo si realizza dinamicamente tramite loperatore new Esempio:
Data d = new Data();

EeHo di new:

Costruisce un nuovo oggeHo di Apo Data ResAtuisce il riferimento alloggeHo appena creato

Data() un metodo parAcolare chiamato COSTRUTTORE


Ha lo stesso nome della classe, si riconosce come metodo dalle parentesi ()

Il riferimento viene conservato nella variabile d per potere usare loggeHo

Dierenze tra dichiarazione e creazione


Data data; data = new Data( ); data = new Data( );

data

Creato con la seconda new. Il riferimento al primo oggeHo Data perso. Non c pi modo di accedere alloggeHo. LoggeHo verr distruHo dal garbage collector.

Creato con la prima new

Data

Data

Condivisione (sharing)
Un oggeHo condiviso tra due variabili se entrambe accedono a esso L'assegnamento di variabili di Apo riferimento genera condivisione Se oggeM condivisi sono modicabili, le modiche apportate aHraverso una variabile sono visibili anche aHraverso l'altra (side eect)

Allocazione stack vs. heap


Quando un metodo termina, tuHe le variabili del corrispondente record di aMvazione sono distruHe per gli oggeM creaA sullo heap NON sono necessariamente distruM

static Data foo() { d xxx Data d = new Data(1,1,2005); return d; } public static void main(String[] args) { Data x = foo(); x xxx }

public

1 1 2010

d esiste solo sullo stack durante lesecuzione di foo(), ma viene deallocata quando foo() termina
LoggeHo costruito conAnua a vivere sullo heap!!!

Tipi array
Dato un Apo T (predenito o denito dallutente) un array di T denito come
T[]

Similmente sono dichiaraA gli array mulAdimensionali


T[][] T[][][]

Esempi
int[] float[] Persona[]

Dichiarazione e inizializzazione
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}};

Il caso degli array


In mancanza di inizializzazione, la dichiarazione di un array non alloca spazio per gli elemenA dellarray Lallocazione si realizza dinamicamente tramite loperatore:
new <Apo> [<dimensione>]
int[] i=new int[10]; i={10,11,12}; float[][] f=new float[10][10]; Persona[] p=new Persona[30];

Se gli elemenA non sono di un Apo primiAvo, loperatore new alloca solo lo spazio per i riferimenA

Array di oggetti: Definizione


A
Person[ ] person; person = new Person[20]; person[0] = new Person( );

E denita solo la variabile person. Larray vero e proprio non esiste

person

Array di oggetti: Definizione


Person[ ] person;

person = new Person[20]; person[0] = new Person( );

Ora larray stato creato ma i diversi oggeM di Apo Person non esistono ancora.

person 0 1 2 3 4 16 17 18 19

Array di oggeM: Denizione


Person[ ] person; person = new Person[20];

C
person

person[0] = new Person( );

Un oggeHo di Apo persona stato creato e un riferimento a tale oggeHo stato inserito in posizione 0.

16 17 18 19

Person

Array di oggeM vs. array di Api base


Listruzione: oat f[] = new oat[10]; crea un ogge<o di =po array di oat e alloca spazio per 10 oat f 0 1 2 3 4 5 6 7 8 9 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 Listruzione: Person p[] = new Person[10]; crea un ogge<o di =po array di Person e alloca spazio per 10 riferimen= a oggeE di =po Person f Non viene allocato spazio per gli oggeE veri e propri 0 1 2 3 4 5 6 7 8 9

Loop generalizzato per collezioni


Se abbiamo una collezione C di elemenA di Apo T, possiamo iterare su di essi scrivendo
for (T x: C) { //si legge for each x in C // esegui azioni su x }

equivalente a scrivere
for (int i = 0; i < C.size(); i++) { T x = C.get(i); // esegui azioni su x }

Anche gli array sono collezioni, quindi

Esempio per array


int sum(int[] a) { int result = 0; for (int n : a) result += n; return result; }

n indica il generico elemento dell'array, NON l'indice! Un esempio pi chiaro: array di Person
int sumAge(Person[] a) { int result = 0; for (Person p: a) result += p.getAge(); return result; }

Programmazione in the large

Tanto per cominciare


public class Automobile { private String colore, marca, modello; private int cilindrata, numPorte; private boolean accesa; }

Metodi
public class Automobile { private String colore, marca, modello; private int cilindrata, numPorte; private boolean accesa; public void accendi(){ accesa=true; } public boolean puoPartire(){ return accesa; } public void dipingi(String col){ colore=col; } public void trasforma(String ma, String mo){ marca=ma; modello=mo; } }

Chiamata di metodi
Vengono valutaA i parametri aHuali Viene creato il record di aMvazione sullo stack
spazio per i parametri formali spazio per le variabili locali

Esecuzione del corpo Regola per il passaggio parametri


I parametri il cui Apo uno dei Api semplici sono passaA per copia I parametri il cui Apo un Apo riferimento sono passaA per riferimento

Passaggio parametri e reference


public class Data { Quando copiaIn termina d2 3/2/1984 private int giorno; private int mese; private int anno; xxx 1 d 1 public void copiaIn(Data d){ d2 xxx 1990 d.giorno = giorno; d.mese = mese; d.anno = anno; } 3 d1 yyy public static void main(String[] args){ 2 Data d1 = new Data(3,2,1984); 1984 Data d2 = new Data(1,1,1990); d1.copiaIn(d2); } }

Visibilit dei nomi


Le variabili locali ad un metodo (o i parametri formali) possono mascherare gli aHribuA della classe Soluzione:
La pseudo-variabile this conAene un riferimento all oggeHo corrente e pu essere uAlizzata per aggirare eventuali mascheramenA

this per aggirare mascheramenA


La pseudo-variabile this conAene un riferimento all oggeHo corrente e pu essere uAlizzata per aggirare eventuali mascheramenA
public class Automobile { private String colore, marca, modello; public void trasforma(String marca, String modello){ this.marca=marca; this.modello=modello; } public static void main(String[] args){ Automobile a = new Automobile(); a.trasforma("Ford", "T4"); } }

a.marca diventa "Ford", a.modello diventa "T4"

Un altro esempio
public class Data { private int giorno; private int mese; private int anno; public void giornoDopo(){ this.giorno++; if (this.giorno > 31){ this.giorno = 1; this.mese++; } } public static void main(String[] args){ Data d1, d2; //d1 e d2 inizializzate qui d1.giornoDopo(); //In giornoDopo this e lo stesso riferimento di d1 d2.giornoDopo(); //In giornoDopo this e lo stesso riferimento di d2 } }

this per resAtuire un riferimento


La pseudo-variabile this pu essere uAlizzata per resAtuire un riferimento all'oggeHo corrente
public class InsiemeDiInteri { public InsiemeDiInteri inserisci(int i){ //modifica this inserendovi lelemento i return this; //restituisce linsieme modificato } } InsiemeDiInteri x,y,z; //qui x e y sono inizializzati opportunamente z = (x.inserisci(2)).unione(y) //utile che inserisci restituisca un insieme

Metodi e aHribuA di classe


Sintassi: Un aHributo di classe condiviso da tuM gli oggeM della classe Si pu accedere a un aHributo di classe senza bisogno di creare un oggeHo tramite la notazione: Un metodo di classe pu essere invocato senza bisogno di creare un oggeHo tramite la notazione: Un metodo di classe pu essere comunque invocato su un oggeHo della classe Il nome di classe pu essere omesso se non ci sono problemi di ambiguit
<nome classe>.<nome metodo>(<par. aHuali>) <nome classe>.<nome aHributo> staAc <denizione dell aHributo o metodo>

Metodi e aHribuA di classe: vincoli


Un metodo staAc pu accedere ai soli aHribuA e metodi staAc Un metodo convenzionale pu accedere liberamente a metodi e aHribuA staAc

Metodi e aHribuA di classe


public class Shape { static Screen screen=new Screen(); // si noti linizializzazione static void setScreen(Screen s) {screen=s;} void show(Screen s) {setScreen(s);} public static void main(String[] args) { Shape.setScreen(new Screen()); // corretto Shape.show(); // errato, show e un metodo normale Shape s1=new Shape(), 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 } }

Metodi e aHribuA di classe


I dischi in una collezione devono essere numeraA in modo progressivo
public class Disc { private static int counter; private int discNumber; Disc(){discNumber = counter++;} public int getDiscNumber(){return discNumber;} public static int getTotalNoOfDiscs(){ return counter;} public static void main(String[] args) { System.out.println(Disc.getTotalNoOfDiscs()); // 0 Disc d1 = new Disc(); Disc d2 = new Disc(); System.out.println(d1.discNumber); // 0 System.out.println(d2.discNumber); // 1 System.out.println(Disc.getDiscNumber()); // errore!!! System.out.println(Disc.getTotalNoOfDiscs()); // 2 } }

AHribuA costanA
possibile denire aHribuA costanA tramite la notazione: Esempio
nal <denizione di aHributo>=<valore>

public class Automobile { int colore; final int BLU=0, GIALLO=1; // e altri void dipingi(int colore) {this.colore=colore;} public static void main(String[] args) { Automobile a=new Automobile(); a.BLU=128; // errato System.out.println("BLU="+a.BLU); // corretto } }

Enumerazioni
Si possono dichiarare Api enumeraA, per modellare insiemi con cardinalit ridoHa
enum Size {SMALL, MEDIUM, LARGE, EXTRA_LARGE}; Size s = Size.MEDIUM;

Size una vera classe: ha esaHamente quaHro istanze Non se ne possono costruire altre Non c bisogno di usare equal per confrontare i valori, basta == s pu essere solo null o uno dei valori enumeraA A una classe enumerata si possono aggiungere costruHore, metodi e aHribuA PermeHono di associare qualsiasi informazione alle costanA enumerate I costruHori sono invocaA solo quando vengono costruite le costanA
public enum Size { SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL"); private String abbreviation; private Size(String abbreviation) { this.abbreviation=abbreviation; } public String getAbbreviation(){ return abbreviation; } }

Enumerazioni
TuHe le classi enumerate sono eredi della classe Enum che ore i seguenA metodi
// resAtuisce la costante enumerata della classe indicata che ha quel nome staAc Enum valueOf(String name) // resAtuisce il nome della costante enumerata String toString()

import java.util.Scanner; public class ProvaString { public static void main (String[] args) { Scanner in = new Scanner(System.in); String str = in.next(); Size siz = Enum.valueOf(Size.class, str); System.out.println(siz.toString()); } }

Ogni classe enumerata ha un metodo che resAtuisce un array contenente tuM i valori della classe
Size[] valori = Size.values();

Altri metodi
name() resAtuisce il nome della costante enumeraAva ordinal() resAtuisce la posizione (partendo da 0) compareTo() confronta loggeHo corrente C con la variabile enumeraAva passata come parametro e resAtuisce
Un valore negaAvo se C minore del parametro Zero se C uguale al parametro Un valore posiAvo se C maggiore del parametro

Loop generalizzato
enum Color {Red, White, Blue} for (Color c: Color.values()) { . . . }

Un esempio pi ricco: pianeA del sistema solare, associaA alla propria massa e raggio; si pu calcolare il peso di un oggeHo su ogni pianeta

Esempio

public enum Planet { MERCURY (3.303e+23, 2.4397e6), VENUS (4.869e+24, 6.0518e6), EARTH (5.976e+24, 6.37814e6), MARS (6.421e+23, 3.3972e6), JUPITER (1.9e+27, 7.1492e7), SATURN (5.688e +26, 6.0268e7), URANUS (8.686e+25, 2.5559e7), NEPTUNE (1.024e+26, 2.4746e7), PLUTO (1.27e+22, 1.137e6); private final double mass; // in kilograms private final double radius; // in meters Planet(double mass, double radius) { this.mass = mass; this.radius = radius; } public double mass() {return mass;} public double radius() {return radius;} // universal gravitational constant (m^3 kg^-1 s^-2) public static final double G = 6.67300E-11; public double surfaceGravity() {return G * mass / (radius * radius);} public double surfaceWeight(double otherMass) {return otherMass * surfaceGravity();} }

A parAre dal peso di un corpo sulla terra, calcola e stampa il peso su tuM gli altri pianeA
public static void main(String[] args) { double earthWeight = Double.parseDouble(args[0]); double mass = earthWeight/EARTH.surfaceGravity(); for (Planet p : Planet.values()) System.out.printf("Your weight on %s is %f%n", p,p.surfaceWeight(mass)); }

Esempio

52

Overloading di metodi
Allinterno di una stessa classe possono esservi pi metodi con lo stesso nome purch si disAnguano per numero e/o Apo dei parametri In Java lintestazione di un metodo comprende il numero, il Apo e la posizione dei parametri; non include il Apo del valore resAtuito UAle per denire funzioni con codice dierente ma con eeM simili su Api diversi
AHenzione: Il Apo del valore resAtuito non basta a disAnguere due metodi

Metodi overloaded devono avere intestazioni diverse

Esempio
public class Prova { public int max(int a, int b, int c) {...} public double max(double a, double b) {...} public int max(int a, int b) {...} }

Ogni volta viene chiamata la funzione "giusta


public static void main(String[] args){ Prova p = new Prova(); p.max(2,3,5); p.max(2.3, 3.14); p.max(2,3); }

I costruHori sono un esempio Apico

Creazione e distruzione
Se limplementazione deve essere private, lunico modo per inizializzare un oggeHo specicare uno o pi metodi parAcolari, chiamaA costruHori Il costruHore svolge due operazioni fondamentali, obbligandoci a denirle insieme: A dierenza del C, in Java non necessario deallocare esplicitamente gli oggeM
Lallocazione della memoria necessaria a contenere loggeHo Linizializzazione dello spazio allocato, assegnando opportuni valori Il garbage collector si occupa di questo: una rouAne di sistema che provvede automaAcamente a liberare memoria quando serve (invece in C/C++) La creazione di un oggeHo comporta sempre linvocazione di un costruHore

Esempio di costruHore
public Data(int g, int m, int a){ giorno = g; mese = m; anno =a; } Data d = new Data(20,3,2007);

Crea un oggeHo d di Apo Data e lo inizializza al 20/03/2007 Unimplementazione pi sosAcata potrebbe controllare che la data proposta sia legale, riutando il 31/2/2007

CostruHori di default
Se non si denisce nessun costruHore, il compilatore fornisce il costruHore di default (senza parametri), che svolge le seguenA funzioni:
Alloca lo spazio per gli aHribuA di Apo primiAvo Alloca lo spazio per i riferimenA agli aHribuA di Apo denito dallutente Inizializza a null tuM i riferimenA, a 0 tuHe le variabili numeriche, a false tuM i boolean

Il costruHore di default (senza parametri) viene fornito dal compilatore a meno che non si deniscano altri costruHori

I costruHori: esempio
public class C { private int i1; private int i2; } public class Esempio { public static void main(String args[]) { CorreHo perch il compilatore ha inserito automaAcamente il C x = new C(); costruHore di default x = new C(5,7); } } Sbagliato, non esiste nessun costruHore che prenda due parametri

public class C { private int i1; private int i2; public C(int a1, int a2) { i1 = a1; i2 = a2;} public C(int a) { i1 = a; i2 = a;} }

MolA costruHori
z y C i1 = 1 i2 = 1 C i1 = 1 i2 = 4

public class Esempio { x public static void main(String args[]) { C x, y, z;

x = new C(); y = new C(1); z = new C(1,4);

Sbagliato, visto che il programmatore ha denito un costruHore, il compilatore non aggiunge quello di default CorreHo, esiste un costruHore che prende un parametro intero CorreHo, esiste un costruHore che prende due parametri interi

Ulteriore esempio
public class Automobile { private String colore, marca, modello; private int cilindrata, numPorte; private boolean accesa; public Automobile(String col, String mar, String mod) { colore=col; marca=mar; modello =mod; } public Automobile() { // se serve e necessario definirlo anche se e come quello di // default, perche ce un altro costruttore colore=marca=modello=null; cilindrata=numPorte=0; } public void accendi() {accesa=true;} public boolean puoPartire() {return accesa;} public void dipingi(String col) {colore=col;} }

Ancora sui costruttori


possibile invocare un costruttore dallinterno di un altro tramite la notazione
this(<elenco di parametri attuali>);

Tuttavia il this deve essere la prima istruzione. Esempio:


import java.util.Calendar; public Data(int g, int m, int a){ if (dataValida(g,m,a)) {// dataValida e' un metodo statico giorno = g; mese = m; anno = a; } else ... } public Data(int g, int m) { //giorno e mese + anno corrente this(g,m,Calendar.getInstance().get(Calendar.YEAR)); }

Reference e operatore ==
Loperatore di confronto == confronta i valori dei riferimenA e non gli oggeM!
d1 xxx 1 12 2001 d2 yyy false: d1 e d2 sono riferimenA a oggeM diversi quindi hanno indirizzi diversi 1 12 2001 giorno mese anno giorno mese anno

Data d1 = new Data(1,12,2001); Data d2= new Data(1,12,2001); if (d1==d2) { ...

d1=d2; (anche se hanno gli stessi valori per gli aHribuA) e

d1 == d2 diventa true: lindirizzo contenuto in d1 diventa uguale allindirizzo contenuto in d1 (diventano idenAci)

Confronto di uguaglianza
Metodo equals( ) consente di vericare se due oggeM sono uguali (nel senso che hanno lo stesso valore dello stato)
per String: contengono la stessa sequenza di caraHeri

Dice se due oggeM sono equivalenA


Che cosa ci esaHamente signichi dipende dal Apo dell'oggeHo
per esempio, due insiemi sono equivalenA se contengono gli stessi elemenA, indipendentemente dall'ordine di inserimento va pertanto spesso ridenita

Uso
String stringa1 = "Luciano; String stringa2 = "Giovanni; Stringa1.equals(stringa2); //false String b = new String("Ciao"); String c = new String("Ciao"); if (b.equals(c)); //true

Tipi riferimento per i Api primiAvi


I Api primiAvi sono comodi, ma a volte si preferirebbe usarli come riferimento, per omogeneit Java fornisce classi predenite
Integer, Character, Float, Long, Short, Double (sono in java.lang) Un oggeHo Integer conAene un int, ma viene inizializzato solo con i costruHori
Il Apo Integer immutabile

Esempi
Integer i; // qui i vale null! i = new Integer(5); //i e un rif. a oggetto che contiene 5 Integer x = i; // sharing: x e i stesso oggetto int y = x.intValue(); // vecchio modo i = y; // boxing automatico y = i; // unboxing automatico i = 3; // come sopra

Catene puntate
Un oggetto pu avere attributi che sono ancora oggetti o metodi che restituiscono oggetti: accesso a metodi e attributi avviene a catena

Esempi
System.out.println();

out aHributo pubblico (staAco) di classe System La classe di out fornisce il metodo println()
String b = new String("Ciao"); String a = b.substring(1).substring(2); System.out.println(a); //che oggetto e a?

Operatore . associativo a sinistra:


(b.substring(1)).substring(2); (System.out).println();

Inizializzazione e accesso
public class Persona { private String nome; private Persona padre; private int eta; public Persona(String n) { nome = n; padre = null; eta = 0;} public void setPadre(Persona p) { padre = p; } public void setEta(int e) { eta = e; } } public class Esempio { public static void main(String[] args) { Persona paolo, pietro; int i = 20; paolo = new Persona("Paolo"); paolo.setEta(i); i = 30; // quanto vale paolo.eta? pietro = new Persona("Pietro"); pietro.setEta(i); paolo.setPadre(pietro); // quanto vale paolo.padre.eta? pietro.setEta(i+1); // quanto vale paolo.padre.eta ? } } Persona String nome Persona padre setEta setPadre paolo i 30 20 Persona nome = Paolo padre = setEta setPadre 20 eta = 0 Persona nome =Pietro padre = setEta setPadre 31 30 eta = 0 pietro int eta

Ereditariet
possibile stabilire una relazione soHoclasse_di () fra le classi di un programma Java
relazione dordine parziale (riessiva e transiAva) public class B extends A {}

A classe base, o antenato, o padre, o superclasse, B classe derivata, o discendente, o glio, o erede, o soHoclasse,

Relazione di ereditariet
La soHoclasse eredita tuHa limplementazione (aHribuA e metodi) della superclasse
Gli aHribuA e metodi della superclasse sono implicitamente deniA anche nella soHoclasse (ma con alcune dierenze che vedremo fra poco)

Una soHoclasse pu aggiungere nuovi aHribuA e metodi ma anche ridenire i metodi delle sue superclassi
Lasciando invariato numero e Apo dei parametri (overriding)

Un semplice esempio
public class Automobile { private String modello; private boolean accesa; public Automobile(String modello) { this.modello=modello; this.accesa = false; } public void accendi() {accesa=true;} public boolean puoPartire() {return accesa;} } public class AutomobileElettrica extends Automobile{ private boolean batterieCariche; public void ricarica() {batterieCariche=true;} ... } }

Gerarchia a pi livelli
Figure perimeter area pixel width color scale() rotate() draw()

ClosedFigure

OpenFigure

numberOfSides Polygon Ellipse

Rectangle

Overriding
Una soHoclasse pu ridenire limplementazione di un metodo
Lintestazione del metodo non deve cambiare Lintestazione non include il Apo resAtuito, che quindi pu cambiare secondo le regole della covarianza
public class AutomobileElettrica extends Automobile{ private boolean batterieCariche; public void ricarica() {batterieCariche = true;} ... } public void accendi() {// OVERRIDING // accensione auto elettrica e diversa da quella // di auto a benzina la reimplementiamo } }

Pseudo variabile super


Allinterno di un metodo della soHoclasse ci si pu riferire ai metodi della superclasse:
super.<nome metodo>(<lista par. aHuali>) public class AutomobileElettrica extends Automobile{
private boolean batterieCariche; public void ricarica() {batterieCariche=true;} public void accendi() {// OVERRIDING if(batterieCariche) super.accendi(); else System.out.println("Batterie scariche"); } }

CostruHori
I costruHori non sono ereditaA perch occorre inizializzare anche i nuovi aHribuA
Per inizializzare gli aHribuA private ereditaA, allinterno di un costruHore possibile richiamare il costruHore della superclasse tramite:
super(<lista di par. aHuali>) posta come prima istruzione del costruHore

Se il programmatore non chiama esplicitamente un costruHore della superclasse, il compilatore inserisce automaAcamente il codice che invoca il costruHore di default della superclasse (che potrebbe non esistere!)
In AutomobileEleHrica:

public AutomobileElettrica(String modello) { super(modello); //qui inizializza modello e accesa batterieCariche=false; }

Object
In mancanza di unindicazione dierente, una classe Java estende la classe Object La classe Object fornisce alcuni metodi tra i quali:
public boolean equals(Object); public String toString(); public Object clone();

String
Le stringhe sono immutabili (non si possono aggiungere o togliere caraHeri a una stringa, ma occorre costruirne una nuova) CostruHori: Operatore di concatenamento + Metodi pubblici:
il primo ha posizione 0

String() String(String s)

int length() resAtuisce la lunghezza di una stringa char charAt(int index) resAtuisce il char alla posizione index String substring(int beginIndex) (parte da 0)

Esempio
public class ProvaString { public static void main (String[] args) { String a = new String(); //a e una ref a stringa vuota String b = new String("Ciao"); //b e una ref a Ciao: //abbreviazione: String b = Ciao; String c = new String(b); //Ora c e copia di b String d = b; //d e b sono alias System.out.println(b + " " + c + " " + d); } }

Lassegnamento d=b un assegnamento dei riferimenA


Non si copia loggeHo!

InformaAon Hiding

Package
Le classi sono raggruppate in package
Un package raggruppa classi denendo regole di visibilit

Se una classe C visibile nel package A, ma dichiarata nel package B, questa viene denotata come B.C
quindi si possono usare liberamente gli stessi nomi in package diversi, senza generare confusione

Package
Una directory che conAene una o pi compilaAon unit Introduce un nuovo ambito di visibilit dei nomi:
unit con lo stesso nome possono stare in package diversi

ConAene un insieme di classi pubbliche ed un insieme di classi private al package ( friendly ) Le classi pubbliche si possono importare in altri package

CompilaAon unit
Un le che conAene la dichiarazione di una o pi classi (o interfacce)
Una sola dichiarata pubblica (public class) e avente lo stesso nome del le

C al pi un solo metodo main Si pu specicare il package di appartenenza (lo stesso per tuHe)
se non si specica, si assume un package senza nome di default

Visibilit delle classi


public
sono visibili a tutti con import del package Il file deve avere lo stesso nome al pi una public class per ogni file

"friendly
sono visibili solo allinterno dello stesso package/compilation unit possono stare in un file con altre classi

Esempio
package myTools.text; public class TextComponent { . . .Zzz z; } package myFigs.planar; public class DrawableElement { . . . } class xxx { . . . }

package myTools.text; public class yyy { . . . } class Zzz{ . . . }

compilaAon units

Visibilit di aHribuA e metodi


AHribuA e metodi di una classe vengono sempre ereditaA e possono essere:
public private
sono visibili a tuM sono visibili solo allinterno della classe non sono visibili nelle soHoclassi sono visibili alle classi nello stesso package sono visibili anche alle soHoclassi sono visibili alle classi nello stesso package sono visibili solo alle soHoclassi nello stesso package

protected friendly

InformaAon hiding
Una propriet public una promessa agli uAlizzatori della classe: La promessa molto vincolante
Meglio promeHere poco! La propriet sar disponibile e non cambier, perlomeno dal punto di vista degli uAlizzatori della classe

TuHe le propriet per cui ci si vuole garanAre la possibilit di modica o eliminazione devono essere private
Al massimo, ma solo se indispensabile, friendly
meglio private per le propriet helper di una classe Se un aHributo friendly e qualcuno lo usa non possiamo pi cambiarlo!!!

InformaAon hiding
fortemente consigliato che gli aHribuA di una classe public siano private o friendly
Usare metodi per accedervi!

I metodi che possono essere usaA dagli uAlizzatori "esterni" della classe dovrebbero essere public
Gli aHribuA friendly sono usaA solo quando le classi all'interno dello stesso package devono avere accesso privilegiato
p. es. Una classe Lista deve usare una classe Nodo che implementa i nodi della Lista: uAle che Lista possa accedere ai campi di Nodo, ma gli uAlizzatori di Lista non devono potere accedere a Nodo

Accesso ai membri private


Le soHoclassi non possono accedere agli aHribuA (e metodi) private delle superclassi! sbagliato scrivere:
public void accendi() { if (batterieCariche) accesa = true; }

perch accesa private nella superclasse!

Polimorfismo

Ereditariet
Una classe denisce un Apo Una soHoclasse (transiAvamente) denisce un soHoApo Un oggeHo del soHoApo sosAtuibile a un oggeHo del Apo Si disAngue tra

Apo staAco: il Apo dichiarato Apo dinamico (o aHuale): il Apo dell'oggeHo aHualmente assegnato

Java garanAsce che ci non compromeHa la type safety (vedremo come) Il compilatore verica che ogni oggeHo venga manipolato correHamente in base al Apo staAco Il linguaggio garanAsce che a run Ame non sorgono errori se invece si opera su un oggeHo il cui Apo dinamico un soHoApo del Apo staAco

Esempio
public class UsaAutomobile { public static void partenza(Automobile p) { if (p.puoPartire()) p.accendi(); } public static void main(String args[]) { Automobile myCar = new AutomobileElettrica("T");// legale!! partenza(myCar); //funziona anche con AutomobileElettrica } }

Polimorsmo
L'esempio precedente un caso di polimorsmo Polimorsmo la capacit per un elemento sintaMco di riferirsi a elemenA di diverso Apo In Java una variabile di un Apo riferimento T pu riferirsi ad un qualsiasi oggeHo il cui Apo sia T o un soHoApo di T Similmente un parametro formale di un Apo riferimento T pu riferirsi a parametri aHuali il cui Apo sia T o un soHoApo di T

Tipo dinamico e Apo staAco


Il Apo staAco quello denito dalla dichiarazione
Automobile myCar;

Il Apo dinamico denito dal costruHore usato per denirlo


AutomobileElettrica yourCar = new AutomobileElettrica();

In Java, il Apo dinamico pu essere soHoApo del Apo staAco


Automobile myCar = new Automobile(); AutomobileElettrica yourCar = new AutomobileElettrica(); myCar = yourCar;

Assegnamento polimorco
A un oggeHo di Apo staAco T si pu sempre assegnare un oggeHo il cui Apo staAco S soHoApo di T (ma non viceversa) Questo consente che il Apo dinamico possa essere soHoApo di quello staAco
Automobile myCar = new AutomobileEleHrica();

Il compilatore verica che ogni oggeHo venga manipolato correHamente solo in base al Apo staAco La regola precedente garanAsce che a runAme non sorgono errori se si opera su un oggeHo il cui Apo dinamico un soHoApo del Apo staAco

Uso delle classi dellesempio


Automobile myCar = new Automobile("Ford"); AutomobileElettrica yourCar = new AutomobileElettrica("E1"); myCar = yourCar;
myCar xxx Ford false modello accesa

yourCar

xxx

El false true

modello accesa baHerieCariche

Chiamata di un metodo
Automobile myCar = new AutomobileElettrica(); myCar.puoPartire(); //OK, chiama metodo di Automobile myCar.accendi(); //OK, chiama metodo di AutomobileElettrica myCar.ricarica(); //KO, ricarica non e metodo di Automobile AutomobileElettrica yourCar = new AutomobileElettrica (); yourCar.ricarica(); //OK, chiama metodo di AutomobileElettrica

Polimorsmo e binding dinamico


In Java, a fronte della invocazione x.f(x1,...,xn), limplementazione scelta per il metodo f dipende dal Apo dinamico di x e non dal suo Apo staAco Il legame (binding) tra il metodo invocato e il metodo aMvato dinamico, dipende dal Apo aHuale dell'oggeHo

Esempio
public class UsaAutomobile { public static void partenza(Automobile a) { a.accendi(); //funziona anche con AutomobileElettrica } public static void main(String args[]) { Automobile a1 = new Automobile("Ford"); Automobile a2 = new AutomobileElettrica("T"); a1.accendi(); //a run-time chiama implementazione di Automobile a2.accendi(); //a run-time chiama implementazione di AutomobileElettrica partenza(a2); // solo a run time si puo conoscere il tipo effettivo } }

Binding dinamico
public static void partenza(Automobile a) { a.accendi(); }

Quale implementazione del metodo accendi() chiamare


Quella di Automobile o quella di AutomobileEleHrica? Il Apo eeMvo del parametro a noto solo quando accendi viene chiamato, cio a runAme

Il compilatore non genera il codice per eseguire il metodo, ma genera il codice che cerca limplementazione giusta in base al Apo eeMvo di a e la esegue
Questo si chiama dispatching

Overloading e overriding
Overriding non va confuso con overloading
public class Punto2D{ public float distanza(Punto2D p){} } public class Punto3D extends Punto2D { public float distanza(Punto3D p){}//OVERLOADING!!! }

Il metodo distanza di Punto3D ha unintestazione diversa da quella di distanza dichiarato in Punto2D:


Punto2D p = new Punto3D(); p.distanza(p); //chiama Punto2D.distanza(Punto2D)

NON overriding non si applica binding dinamico

Regola per chiamata metodi


Il compilatore, quando trova una chiamata di un metodo x.m(p) risolve staAcamente loverloading, individuando la segnatura del metodo chiamato in base al Apo staAco P del parametro aHuale p e al Apo staAco X di x Il binding dinamico si applica a run-Ame: il codice sceglie a runAme il metodo pi vicino tra quelli che hanno il protoApo X.m(P) stabilito staAcamente

Esempio
public class Punto2D{public float distanza(Punto2D p){}} public class Punto3D extends Punto2D {public float distanza(Punto3D p){}} public void static void main(String[] args){ Punto2D p1,p2; Punto3D p3; p1 = new Punto2D(3,7); p2 = new Punto3D(3,7, 4); System.out.println(p1.distanza(p2));//metodo di Punto2D System.out.println(p2.distanza(p1)); //Punto2D p3 = new Punto3D(6,7, 5); System.out.println(p2.distanza(p3)); //Punto2D System.out.println(p3.distanza(p1)); //Punto2D System.out.println(p1.distanza(p3)); //Punto2D Punto3D p4 = new Punto3D(6,1, 5); System.out.println(p3.distanza(p4)); //Punto3D }

Classi e metodi astraM


Un metodo astraHo un metodo per il quale non viene specicata alcuna implementazione Una classe astraHa se conAene almeno un metodo astraHo Non possibile creare istanze di una classe astraHa Le classi astraHe sono molto uAli per introdurre delle astrazioni di alto livello

Classi e metodi astraM


abstract class Shape { static Screen screen = new Screen(); Shape(){} abstract void show(); } class Circle extends Shape { void show() { } }

Shape s=new Shape(); //ERRATO Circle c=new Circle(); //CORRETTO Shape s=new Circle(); //CORRETTO

Classi e metodi nal


Se vogliamo impedire che sia possibile creare soHoclassi di una certa classe la deniremo nal Similmente, se vogliamo impedire loverriding di un metodo dobbiamo denirlo nal
class C {final void f(){} class C1 extends C { void f(){} //ERRATO } final class C {...} class C1 extends C //ERRATO

I limiA dellereditariet semplice


L ereditariet semplice non permeHe la descrizione di numerose situazioni reali
Supponiamo di avere una classe GiocaHolo ed una classe Automobile In assenza di ereditariet mulApla non posso denire la classe AutomobileGiocaHolo

La soluzione di Java

DisAngue tra una gerarchia di ereditariet (semplice) ed una gerarchia di implementazione (mulApla) introducendo il costruHo interface

Interfacce
Una interfaccia come una classe che pu avere solo aHribuA costanA e i cui metodi sono tuM pubblici e astraM Sintassi:
interface <nome> { <lista di denizione di aHribuA costanA e metodi privi di corpo> }

Gli aHribuA dichiaraA in una interfaccia sono


visibili alla classe che la implementa immodicabili (staAc nal)

public interface Scalable { int SMALL=0, MEDIUM=1, BIG=2; //static e final void setScale(int size); }

Interfacce ed ereditariet
Una interfaccia pu ereditare da una o pi interfacce
interface <nome> extends <nome1>,..,<nomen> { ... }

La gerarchia di implementazione
Una classe pu implementare una o pi interfacce, ma estendere al pi una classe
se la classe non astraHa deve fornire unimplementazione per tuM i metodi presenA nelle interfacce che implementa altrimenA la classe astraHa

Sintassi:
class <nome> extends <nome0> implements <nome1>,..,<nomen> {...}

Esempio
public interface Bicycle { void changeCadence(int newValue); void changeGear(int newValue); void speedUp(int increment); void applyBrakes(int decrement); } public class ACMEBicycle implements Bicycle{ int cadence = 0; int speed = 0; int gear = 1; public void changeCadence(int newValue) { cadence = newValue; } public void changeGear(int newValue) { gear = newValue; } public void speedUp(int increment) { speed = speed + increment; } public void applyBrakes(int decrement) { speed = speed - decrement; } void printStates() { System.out.println("cadence:"+cadence+" speed:"+speed+" gear:"+gear); } }

Conversioni automatiche di tipo

Promozioni
byte -> short, int, long, oat, double short -> int, long, oat, double int -> long, oat, double long -> oat or double oat -> double char -> int, long, oat, double

Conversioni forzate: casAng


possibile forzare una conversione di Apo aHraverso loperatore di casAng: Tra Api primiAvi sono consenAte le seguenA conversioni forzate (quando possibile e con perdita di informazione)
short char int long oat double byte -> -> -> -> -> -> -> byte, char byte, short byte, short, char byte, short, char, int byte, short, char, int, long byte, short, char, int, long, oat char (<Apo>)<espressione>

CasAng in generale
possibile forzare esplicitamente la conversione da un Apo riferimento T ad un soHoApo T1 purch:
Il Apo dinamico dellespressione che converAamo sia un soHoApo di T1

Animale a = ; Gatto mao = ; a = mao; //OK assegnazione polimorfica mao = (Gatto)a; //corretto (casting) perche a e un gatto

instanceof
Per evitare errori runAme e stabilire qual il Apo dinamico di un oggeHo si pu usare loperatore instanceof
Object a; int i = System.in.read(); if (i>0) a = new String(); else a = new Integer(5); if (a instanceof String) return a.equals("abcd")

instanceof e equals
public class Data { private int giorno; private int mese; private int anno; public int leggiGiorno(){} public boolean equals(Object o) { if (!(o instanceof Data)) return false; Data d= (Data) o; return (giorno==d.giorno && mese == d.mese && anno == d.anno); } }

ArrayList
Gli arrayList sono contenitori estendibili e accorciabili dinamicamente
Prima di JDK5 potevano contenere solo oggeM Object Da JDK5 sono parametrici (generici) rispeHo al Apo degli oggeM contenuA Prima ancora cerano i Vector, analoghi ad ArrayList non generici

ArrayList
import java.util.ArrayList; ArrayList<Person> team = new ArrayList<Person>(); team.add(new Person("Bob")); team.add(new Person("Joe")); team.size()

ArrayList
Per accedere agli elemenA occorre usare i metodi get e set (fanno riferimento a indici che iniziano da 0)
team.get(1); //restituisce la Person di nome Joe team.set(0, new Person("Mary")); //sostituisce Mary a Bob

I metodi add(indice, oggeHo) e remove(indice) aggiungono e tolgono un elemento nella posizione indicata, alterando la lunghezza dellArrayList

team.add(1, new Person("Sue")); //ora ci sono Mary, Sue, Bob team.remove(0); // rimuove Mary, ora ci sono Sue e Bob

ArrayList
add e remove sono operazioni costose perch comportano la traslazione di segmenA dell ArrayList
Il metodo set NON deve essere usato per inserire un elemento in una posizione che non c
team.set(4, new Person("Jack")); // scorretto

ma solo per sosAtuire un oggeHo gi presente in quella posizione


for(Person p: team){ //fa qualcosa con la persona p }

Genericit e soHoApi
Alcune cose sembrano andare contro lintuizione
List<String> ls = new ArrayList<String>(); List<Object> lo = ls; // ERRORE IN COMPILAZIONE lo.add(new Object()); String s = ls.get(0); // ERRORE: tenta di assegnare un Object a una String!

Qualche considerazione
Una lista di String una lista di Object?
NO! altrimenA tramite una variabile lista di Object si pu inserire un Object in una lista di String e quando si tenta di estrarre, tramite una variabile lista di String, un oggeHo String, si verica un errore In generale, se Gen<T> una classe generica e se ClassB soHoclasse di ClassA allora Gen<ClassB> NON soHoclasse di Gen<ClassA> E quindi una lista di Object NON soHoclasse di una lista di String

Come funzionano
Per rendere correHa l inserzione c.add(o) dobbiamo chiamare fromArrayToCollecAon con parametri in cui il Apo dellelemento della collezione sia superApo di quello dellarray
static <T> void fromArrayToCollection(T[] a, Collection<T> c) { for (T o : a) {c.add(o);} }

Non occorre indicare esplicitamente i parametri aHuali in corrispondenza ai parametri formali di un metodo generico Ci pensa il compilatore a inferire il Apo del parametro aHuale scegliendo il Apo pi specico (il minimo, nellordinamento tra Api denito dalla gerarchia di ereditariet, tra tuM quelli che rendono legale l invocazione del metodo generico)

Esempi
String[] sa = new String[100]; Collection<String> cs = new ArrayList<String>(); fromArrayToCollection(sa, cs);// T inferred to be String Collection<Object> co = new ArrayList<Object>(); fromArrayToCollection(sa, co);// T inferred to be Object Integer[] ia = new Integer[100]; fromArrayToCollection(ia, cs);// String NON e supertipo di Integer

I/O formaHato
Input

Dobbiamo costruire uno scanner collegato allo standard input stream System.in, poi usare i metodi della classe Scanner
nextLine() legge la prossima riga next() legge la prossima stringa no a uno spazio nextInt() legge il prossimo int nextDouble() legge il prossimo double hasNext() dice se c una stringa in input hasNextInt(), nextFloat(), nextBoolean()

Output

System.out fornisce anche il buon vecchio prin di C, con le solite convenzioni di formaHazione, pi print e println

Esempio
public static void main(String args[]) { Scanner in = new Scanner(System.in); System.out.println("Come ti chiami?"); String nome = in.nextLine(); System.out.println("Quanti anni hai?"); int eta = in.nextInt(); System.out.println("Ciao "+nome+" tra un anno avrai " +(eta+1)+" anni"); }

Gestione delle eccezioni

Situazioni eccezionali
Un metodo (utente o di libreria) deve poter segnalare l impossibilit di produrre un risultato signicaAvo o la propria terminazione scorreHa Soluzioni
Apertura di un le (ma il le non esiste) Calcolo della radice quadrata di un numero (ma il numero negaAvo) Terminazione del programma
SpeHa al chiamante e non al chiamato

ResAtuire un valore convenzionale che rappresenA lerrore Portare il programma in uno stato scorreHo
Si usa una variabile globale ERROR Ad esempio, si chiama un metodo ERROR(...) Pu non essere faMbile Il chiamante potrebbe dimenAcarsi di controllare

Usare un metodo predenito per la gesAone degli errori


Centralizza la gesAone degli errori (che speHerebbe al chiamante) Rende dicoltoso il riprisAno

GesAone esplicita delle eccezioni


Una procedura pu terminare normalmente Uneccezione un oggeHo speciale resAtuito dal metodo
con un risultato valido o sollevando uneccezione Le eccezioni vengono segnalate al chiamante che pu gesArle Le eccezioni hanno un Apo (Classe) Le eccezioni possono contenere daA che danno indicazioni sul problema incontrato Le eccezioni possono essere denite dallutente (personalizzazione)
Esempi: DivisionByZeroExcepAon, NullPointerExcepAon

Eccezioni in Java
Un'eccezione pu essere caHurata e gesAta aHraverso il costruHo
try {<blocco>} catch(ClasseEccezione e) {<codice di gesAone>}
try { x = x/y; } catch (DivisionByZeroException e) { // e e loggetto eccezione // codice per gestire leccezione // Qui e possibile usare e } // istruzione successiva, da eseguire se non ce stata // eccezione o se catch e riuscito a recuperare

Pi rami catch
Un ramo catch(Ex e) pu gesAre uneccezione di Apo T se T di Apo Ex o T un soHoApo di Ex Pi clausole catch possono seguire lo stesso blocco try
Ciascuna caHura leccezione del proprio Apo
public void faiQualcosa() { try { leggiFile(); } catch(FileInesistenteException fi) { System.out.println("Ooops! Il file " + fi.getNomeFile() + " non esiste!"); } catch(FileDanneggiatoException fd) { System.out.println("Ooops! Il file " + fd.getNomeFile() + " contiene dati scorretti!"); } }

Propagazione delle eccezioni


Si termina lesecuzione del blocco di codice in cui si vericata leccezione e...
se il blocco di codice corrente un blocco try/catch ed esiste un catch in grado di gesAre leccezione, si passa il controllo al primo di tali rami catch e, completato questo, alla prima istruzione dopo il blocco altrimenA si risalgono eventuali blocchi di codice pi esterni no a trovare un blocco try/catch che contenga un ramo catch che sia in grado di gesAre leccezione, altrimenA... Leccezione viene propagata nel contesto del chiamante la propagazione conAnua no a che si trova un blocco try/catch che gesAsce leccezione se tale blocco non si trova, il programma termina

Flusso in presenza di eccezioni


Flusso:
main aMvato blocco 1 blocco 2 proc1 invocata proc2 invocata blocco 3 blocco 4 ... eccezione! propagazione delleccezione!
main block1 block2 call to proc1 proc2 block3

block4 throw excepAon

proc1 call to proc2

block5

Il ramo nally
Un blocco try/catch pu avere un ramo nally in aggiunta a uno o pi rami catch Il ramo nally comunque eseguito
sia che allinterno del blocco try non vengano sollevate eccezioni sia che allinterno del ramo try vengano sollevate eccezioni gesAte da un catch
In tal caso il ramo nally viene eseguito dopo il ramo catch che gesAsce leccezione

sia che allinterno del blocco try vengano sollevate eccezioni NON gesAte da un catch

Esempio
public class Prova { public void read(String fileName) { try{ FileInputStream f=new FileInputStream(fileName); ... // use f } catch(IOException ex) {...} finally {f.close();} } }

Procedure con eccezioni


Il faHo che un metodo possa terminare sollevando uneccezione dichiarato nella sua interfaccia per mezzo della clausola throws per
Segnalare un comportamento anomalo incontrato durante lesecuzione di unistruzione
int leggiInteroDaInput() throws IOException

public

NoAcare che una precondizione su unoperazione stata violata


public int fact(int n) throws NegativeException

ResAtuire un valore convenzionale


public int search(int[] a, int x) throws NullPointerException, NotFoundException

Sollevare eccezioni
Per sollevare esplicitamente un'eccezione, si usa il comando throw, seguito dalloggeHo (del Apo delleccezione) da lanciare al chiamante Informalmente throw
Termina lesecuzione del blocco di codice che lo conAene, generando un'eccezione del Apo specicato
public int fact(int n) throws NegativeException { if (n<0) throw new NegativeException(); else if (n==0 || n==1) return 1; else return (n*fact(n-1)); }

Tipi di eccezioni
Eccezioni denite tramite classi, soHoApo del Apo Throwable Esistono due Api di eccezioni:
eccezioni checked
soHoApo di ExcepAon
Error Throwable Exception

eccezioni unchecked
soHoApo di RunAmeExcepAon
RuntimeException (checked exceptions)

(unchecked exceptions)

Eccezioni checked
Devono essere dichiarate dai metodi che possono sollevarle (altrimenA si ha un errore in compilazione) Quando un metodo M1 invoca un altro metodo M2 che pu sollevare uneccezione di Apo Ex (checked), una delle due seguenA aermazioni deve essere vera
Linvocazione di M2 in M1 avviene internamente ad un blocco try/catch che gesAsce eccezioni di Apo Ex (quindi, M1 gesAsce leventuale eccezione) Il Apo Ex (o un suo super-Apo) fa parte delle eccezioni dichiarate nella clausola throws del metodo M1 (quindi, M1 propaga leventuale eccezione)

Eccezioni unchecked
Possono propagarsi senza essere dichiarate in alcuna intestazione di metodo e senza essere gesAte da nessun blocco try/catch Pu essere meglio includerle comunque in throws, per renderne esplicita la presenza (ma per il compilatore irrilevante)

Denizione di nuove eccezioni


Gli oggeM di un qualunque Apo T denito dallutente possono essere usaA per sollevare e propagare eccezioni se T denito come soHo- Apo della classe ExcepAon (o RunAmeExcepAon) La denizione della classe che descrive uneccezione non dierisce dalla denizione di una qualsiasi classe denita dallutente

Denizione di nuove eccezioni


Pu possedere aHribuA e metodi propri usaA per fornire informazioni aggiunAve al gestore delleccezione I due costruHori richiamano semplicemente i costruHori di ExcepAon
throw new NewKindOfException("problema!!!") try{....} catch(NewKindOfException ecc){ String s = ecc.toString();System.out.println(s); } public class NewKindOfException extends Exception { public NewKindOfException(){super();} public NewKindOfException(String s){super(s);} }

Eccezioni con un costruHore


public class ProvaEcc { public static void main(String[] args) { int g,m,a; Data d; ... // leggi g, m, a try {d=new Data(g,m,a);} catch(DataIllegaleException e) { System.out.println("Inserita una data illegale"); System.exit(-1); }}} public class Data { private int giorno, mese, anno; private boolean corretta(int g,int m,int a) {...} public class DataIllegaleException extends Exception {};//inner class public Data(int g, int m, int a) throws DataIllegaleException { if(!corretta(g,m,a)) throw new DataIllegaleException(); giorno=g; mese=m; anno=a; }}

Eccezioni unchecked
Il loro uso dovrebbe essere limitato ai casi in cui
Si traHa di eccezioni di Apo aritmeAco/logico C un modo conveniente e poco costoso di evitare leccezione

Leccezione usata solo in un contesto ristreHo Meglio dichiararle comunque in throws quando un metodo le pu lanciare

Ad esempio, le eccezioni aritmeAche: posso sempre, se mi serve, controllare prima di eseguire il calcolo Ad esempio, per gli array, le eccezioni di Apo OutOfBoundExcepAon possono essere evitate controllando in anAcipo il valore dellaHributo length dellarray

Masking
Dopo la gesAone delleccezione, lesecuzione conAnua seguendo il normale usso del programma (leccezione viene gesAta e non si propaga al chiamante) Eccezione usata per vericare una condizione
public static boolean sorted (int[] a) { int prev; try {prev=a[0];} //lancia eccezione se array e vuoto //(era meglio check diretto su a) catch (IndexOutOfBoundsException e){return true;} for (int i=1; i<a.length; i++) { if (prev <= a[i]) prev=a[i]; else return false; } return true; }

Consigli uAli
Aggiungere ai daA correlaA con leccezione lindicazione del metodo che lha sollevata Nel caso in cui la gesAone di uneccezione comporA unulteriore eccezione (reecAng), conservare le informazioni Sebbene sia possibile scegliere liberamente i nomi delle nuove eccezioni denite, buona convenzione farli terminare con la parola ExcepAon Pu essere talvolta uAle prevedere un package contenente tuHe le nuove eccezioni denite
A volte invece conviene denire eccezioni come inner classes