3 - Unità didattica 3.3)
- Tipi di dati non primitivi:
reference
Abbiamo già visto come istanziare oggetti da
una certa classe. Dobbiamo prima dichiarare un oggetto di tale
classe con una sintassi di questo tipo:
NomeClasse nomeOggetto;
per poi istanziarlo utilizzando la parola
chiave new.
Dichiarare un oggetto quindi è del tutto simile a dichiarare un tipo
di dato primitivo. Il "nome" che diamo ad un oggetto è detto "reference".
Infatti, non si sta parlando di una variabile tradizionale bensì di
un puntatore. Possiamo definire un puntatore come una variabile che
contiene un indirizzo in memoria. C’è una sottile e potente
differenza tra la dichiarazione di un tipo di dato primitivo ed uno
non primitivo. Consideriamo ora un esempio, partendo dalla
definizione di una classe che astrae in maniera banale il concetto
di data.
class Data
{
int
giorno;
int mese;
int anno;
}
Data
sarà quindi un tipo di dato non primitivo (astratto) per il nostro
esempio. Come tipo di dato primitivo consideriamo un
double. Consideriamo
le seguenti righe di codice, supponendo che si trovino all’interno
di un metodo main
di un’altra classe:
double
unNumero=5.0;
Data
unGiorno=new Data();
La variabile
unAltroNumero,
assumerà lo stesso valore della variabile
unNumero, ma, le due
variabili, rimarranno indipendenti l’una dall’altra. Infatti, il
valore della variabile
unNumero, sarà copiato nella variabile
unAltroNumero. Se il
valore di una delle due variabili sarà successivamente modificato,
l’altra variabile non apporterà modifiche al proprio valore.
Invece, il reference
unAltroGiorno,
semplicemente assumerà il valore (cioè l’indirizzo) del reference
unGiorno. Ciò
significa che unAltroGiorno
punterà allo stesso oggetto cui punta
unGiorno.
Quindi, se successivamente sarà apportata una
qualche modifica tramite uno dei due reference all’oggetto comune,
ovviamente questa sarà verificabile anche tramite l’altro reference.
Per intenderci:
unGiorno.anno
è sicuramente equivalente a:
unAltroGiorno.anno
- Passaggio di parametri per valore
Come abbiamo già accennato nel precedente
capitolo il passaggio di parametri in Java avviene sempre per
valore. Ciò significa che quando viene invocato un metodo che come
parametro prende in input una variabile, al metodo stesso viene
passato solo il valore (una copia) della variabile, che quindi
rimane immutata anche dopo l'esecuzione del metodo. Per esempio
consideriamo la classe:
class
CiProvo
{
public void cambiaValore(int valore)
{
valore = 1000;
}
}
il seguente frammento di codice:
CiProvo
ogg = new CiProvo();
int
numero = 10;
ogg.cambiaValore(numero);
System.out.println(“il valore del numero è ” + numero);
produrrà il seguente output:
il valore
del numero è 10
Infatti il parametro
valore
del metodo
cambiaValore(),
nel momento in cui è stato eseguito il metodo, non coincideva con la
variabile
numero,
bensì immagazzinava solo la copia del suo valore (10).
Quindi ovviamente la variabile
numero
non è stata modificata.
Stesso discorso vale per i tipi reference: viene sempre passato
il valore del reference, ovvero, l'indirizzo in memoria. Per esempio
consideriamo la seguente classe:
class
CiProvoConIReference
{
public void cambiaReference(Data data)
{
data
= new Data(); // Un oggetto appena istanziato
// ha
le variabili con valori nulli
}
}
il seguente frammento di codice:
CiProvoConIReference ogg = new CiProvoConIReference();
Data
dataDiNascita = new Data();
dataDiNascita.giorno = 26;
dataDiNascita.mese = 1;
dataDiNascita.anno = 1974;
ogg.cambiaReference(dataDiNascita);
System.out.println(“Data di nascita = ” + dataDiNascita.giorno
+ “-”+
dataDiNascita.mese + “-” +dataDiNascita.anno );
produrrà il seguente output:
Data di
nascita = 26-1-1974
Quindi valgono le stesse regole anche per i reference.
N.B.: Attenzione che se il metodo
cambiaReference()
avesse cambiato i valori delle variabili d'istanza dell'oggetto
avremmo avuto un output differente. Riscriviamo il metodo in
questione:
public
void cambiaReference(Data data)
{
data.giorno=29;
// data punta allo stesso indirizzo
data.mese=7
// della variabile dataDiNascita
}
Il fatto che il passaggio avvenga sempre per
valore, garantisce che un oggetto possa essere modificato, e
contemporaneamente, si è certi che dopo la chiamata del metodo il
reference punti sempre allo stesso oggetto.
N.B.: altri linguaggi come il C, permettono anche il passaggio di
parametri “per riferimento”. In quel caso al metodo viene passato
l'intero riferimento, non solo il suo indirizzo, con la conseguente
possibilità di poter mutarne l'indirizzamento. Java ha scelto ancora
una volta la strada della robustezza e della semplicità, favorendola
alla potenza del linguaggio
Obbiettivi e Unità Didattica 3.1) - Pagina 1
Unità didattica 3.2) - Pagina 2
Unità didattica 3.3) - Pagina 3
Unità didattica 3.4) - Pagina 4
Unità didattica 3.5) - Pagina 5
Unità didattica 3.6) - Pagina 6