Metodo
I metodi sono uno strumento che i programmatori usano per strutturare i programmi,
sia per renderli più facili da capire che per permettere il riutilizzo del codice.
Essi consentono al programmatore di concentrarsi su una parte del problema.
I parametri del sottoprogramma rappresentano i dati che il metodo usa per svolgere il
compito assegnato.
Vantaggi dell’uso di metodi:
Possibilità di modularizzare i programmi, rendendoli più leggibili;
Riusabilità del Software: possibilità di riutilizzare porzioni di codice in punti
diversi del programma o in programmi diversi (evita la duplicazione del codice).
1
Metodi
Un metodo
è una sequenza di istruzioni che vengono attivate a seguito di una chiamata.
Lo scambio di informazioni fra metodo invocato e metodo chiamante avviene attraverso il
passaggio di zero o più parametri in ingresso e un (eventuale) valore restituito in uscita.
Parametri in ingresso
sottoprogramma
Valore restituito
Parametri in ingresso
Parametri formali (specificati nella definizione del metodo stesso): simboli che
rappresentano i dati su cui il metodo opera
Parametri attuali (specificati nella chiamata del metodo): dati corrispondenti ai
parametri formali, su cui il metodo effettivamente opera
In Java i sottoprogrammi si chiamano metodi e sono definiti sempre all’interno di una classe.
2
Definizione di metodi
La dichiarazione di un metodo specifica le istruzioni che verranno eseguite quando il
metodo è invocato (chiamato).
Quando viene invocato un metodo, il flusso di controllo passa al metodo ed vengono
eseguite le istruzioni definite nel metodo.
Quando l’esecuzione del metodo termina, il flusso di controllo ritorna al punto in cui
era stato chiamato il metodo e l’esecuzione continua dall’istruzione successiva alla
chiamata.
La chiamata può restituire un valore o no, in dipendenza da come e’ stato definito il
metodo.
3
Flusso di controllo di un metodo
Quando si incontra la chiamata di un metodo il controllo viene trasferito alla prima
istruzione del metodo stesso.
Il flusso di esecuzione torna al codice chiamante quando si incontra una istruzione
return (che restituisce il valore specificato) oppure al termine del codice del metodo
per metodi definiti void.
Il metodo chiamato può essere definito nella stessa classe, nel qual caso per chiamarlo
e’ sufficiente il nome del metodo.
compute
myMethod
myMethod();
4
Passaggio di parametri
Ogni volta che un metodo viene chiamato, i parametri attuali usati nella chiamata
vengono copiati nei parametri formali.
1.
2.
3.
4.
int
int
int
int
val1 = 100;
val2 = 20;
div = 3;
ris = calc(val1, val2, div);
1. static int calc(int num1, int num2, int div) {
2.
int val = (num1 + num2)/div;
3.
return val;
4. }
5
Metodi
1. public class Esempio {
2. static int calc(int num1, int num2, int div) {
3.
int val = (num1 + num2)/div;
4.
return val;
5. }
6. static public void main(String[] args)
{
7.
int val1 = 100;
8.
int val2 = 20;
9.
int ris = 0;
10.
if(args.length > 0){
11.
int div = Integer.parseInt(args[0]);
12.
ris = calc(val1, val2, div);
13.
System.out.println(ris);
14.
}
15. }
16.}
6
Eccezioni
Durante l’esecuzione di un programma possono verificarsi degli errori dovuti a:
dati errati in ingresso o errori di programmazione.
Un buon programma deve prevedere la gestione dei fallimenti individuando e
ripristinando l’errore.
Spesso il punto del programma in cui l’errore si manifesta non coincide con il
punto in cui è possibile ripristinarlo.
7
Eccezioni
Un’eccezione è un oggetto che descrive una situazione inusuale o erronea.
Le eccezioni vengono lanciate da un programma o dalla macchina virtuale, e possono
essere intercettate e gestite.
Si puo’ gestire un’eccezione nei seguenti tre modi:
Non gestire l’eccezione;
Gestire l’eccezione non appena si verifica;
Gestire l’eccezione in un altro punto del programma.
Se un’eccezione viene ignorata dal programma, allora il programma stesso verrà
interrotto producendo un messaggio di errore opportuno.
Il messaggio include il tipo di eccezione lanciata e la pila delle chiamate ai metodi che
consentono di individuare il punto del programma in cui l’eccezione si e’ verificata.
8
Messaggio di segnalazione di eccezione
Se nella classe Esempio assegnassi alla variabile div il valore
0 otterrei il seguente messaggio:
Exception in thread "main"
java.lang.ArithmeticException: / by zero
at Esempio.calc(Esempio.java:3)
at Esempio.main(Esempio.java:10)
generato dalla macchina virtuale che segnala un errore dovuto ad
una divisione per zero.
9
Eccezioni controllate
Le eccezioni controllate richiedono che il metodo in cui si possono verificare le
intercetti e le gestisca direttamente o le elenchi nella clausola throws.
10
Gestione delle Eccezioni
Java mette a disposizione dei meccanismi flessibili per individuare e ripristinare gli
errori di un programma.
La gestione delle eccezioni consente di trasferire il controllo dell’errore dal punto in cui
si manifesta al punto del programma in cui è possibile gestire l’errore ripristinando la
situazione corretta.
L’esecuzione di un programma prevede l’invocazione di metodi in cascata. Quando si
verifica un errore, il metodo che lo ha generato non sempre ha la possibilità di porre
rimedio ad esso, ma potrà delegare il chiamante a gestire direttamente l’eccezione o a
rilanciarla a sua volta.
11
Clausola throw
Per lanciare un’eccezione si usa la clausola throw. Questa si inserisce nel punto del
programma che genera l’eccezione.
Esempio:
static int calc(int num1, int num2, int div) {
if(div == 0)
throw new IllegalArgumentException("Divisore
non valido");
int val = (num1 + num2)/div;
return val;
}
L’eccezione lanciata verrà catturata dal metodo che intende gestirla. Il metodo
competente per la gestione dell’eccezione dovrà utilizzare un blocco try – catch.
12
Blocco try - catch
try {
istruzioni che possono generare l’eccezione
} catch(IOException e) {
gestore dell’eccezione IOException
} catch(IllegalArgumentException e) {
gestore dell’eccezione IllegalArgumentException
}
13
Il blocco try - catch
Per gestire un’eccezione occorre inserire la/e istruzione/i che possono lanciare l’eccezione
all’interno di un blocco try.
Un blocco try e’ seguito da una o più clausole catch che contengono le istruzioni che servono
a gestire la/e eccezione/i.
Ogni clausola catch e’ associata ad un tipo di eccezione.
Ogni blocco try può avere più clausole catch associate.
Ogni clausola catch viene detta gestore di eccezioni.
Quando viene eseguito un blocco try, vengono eseguite tutte le istruzioni contenute nel blocco.
Se non si verificano eccezioni, l’esecuzione continua poi con le istruzioni che seguono il blocco
try (dopo la clausola catch).
Se si verifica un’eccezione all’interno di un blocco try, il controllo passa al gestore di eccezioni
appropriato (blocco catch). Dopo l’esecuzione delle istruzioni della clausola catch, il controllo
passa alle istruzioni che seguono l’intero blocco try – catch.
14
Gestione delle eccezioni
Se un’eccezione non viene intercettata e gestita quando si verifica, il controllo viene
immediatamente restituito al metodo che ha invocato il metodo che l’ha prodotta.
Le eccezioni si propagano finché si incontra un metodo che intercetta e gestisce l’eccezione,
oppure finché non termina anche il metodo main.
Per intercettare un’eccezione ad un livello più esterno, il metodo che produce l’eccezione deve
essere invocato all’interno di un blocco try che possieda la clausola catch appropriata per
gestirla.
Le eccezioni possono essere propagate da un metodo al chiamante con la clausola throws che
segue l’intestazione della definizione del metodo. La clausola throws serve per indicare che
quel metodo può lanciare o propagare una particolare eccezione, se si verifica. E’ obbligatorio
che un metodo che possa generare un’eccezione controllata o la gestisca direttamente o la
propaghi con la clausola throws .
public static void main(String[] args)
throws IOException {
15
Copia di un file
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
// esempio in cui non si gestisce l’eccezione controllata,
// ma si segnala che l’applicazione può generarla (throws).
import java.io.*;
public class CopyBytes {
public static void main(String[] args)
throws IOException {
FileInputStream in = new FileInputStream(args[0]);
FileOutputStream out = new FileOutputStream(args[1]);
int c;
while ((c = in.read()) != -1)
out.write(c);
in.close();
out.close();
}
}
16
Copia di un file
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
// esempio in cui si intercettano due eccezioni controllate.
import java.io.*;
public class Copy {
public static void main(String[] args) {
try {
FileReader in = new FileReader(args[0]);
FileWriter out = new FileWriter(args[1]);
int c;
while ((c = in.read()) != -1)
out.write(c);
in.close(); out.close();
}
catch(FileNotFoundException e) {
System.err.println(e.getMessage());
System.exit(1);
}
catch(IOException e) {
System.err.println(e.getMessage()););
System.exit(1);
}
}
}
17
// esempio di gestione di eccezione in un punto diverso da quello in
// cui l’eccezione viene generata.
public class Esempio {
static int calc(int num1, int num2, int div) {
if(div == 0)
throw new IllegalArgumentException("Divisore non valido!");
int val = (num1 + num2)/div;
return val;
}
static public void main(String[] args)
{
int val1 = 100;
int val2 = 20;
int ris = 0;
if(args.length > 0){
int div = Integer.parseInt(args[0]);
try {
ris = calc(val1, val2, div);
System.out.println(ris);
} catch (IllegalArgumentException e){
System.out.println(e.getMessage());
}
}
}
}
// esempio di gestione di eccezione in un punto diverso da quello in
// cui l’eccezione viene generata. In questo caso si effettua anche
// il ripristino dell’errore.
public class Esempio {
static int calc(int num1, int num2, int div) {
if(div == 0)
throw new IllegalArgumentException("Divisore non valido");
int val = (num1 + num2)/div;
return val;
}
static public void main(String[] args)
{
int val1 = 100, val2 = 20 , ris = 0 ;
boolean done = false;
if(args.length > 0){
int div = Integer.parseInt(args[0]);
while (!done){
try {
ris = calc(val1, val2, div);
done = true;
} catch (IllegalArgumentException e){
System.out.println(e.getMessage());
div = MyUtility.readInt("Inserisci un divisore");
}
}
System.out.println(ris);
}
}
}
Clausola finally
Al blocco try si puo’ associare la clausola opzionale finally che definisce una
sezione di codice che viene eseguita indipendentemente da come si sia usciti dal
blocco try.
Le istruzioni contenute nel blocco finally verranno eseguite sempre sia in caso di
eccezione, che in caso di conclusione normale del blocco try.
Spesso si utilizza per gestire risorse (chiusura di file aperti anche in caso di eccezioni) o
per garantire che alcune parti dell’algoritmo vengano eseguite comunque.
20