Tipi di dati non primitivi: reference
Abbiamo già visto come istanziare oggetti da unacerta classe. Dobbiamo prima dichiarare un oggetto di taleclasse con una sintassi di questo tipo:
NomeClasse nomeOggetto;
per poi istanziarlo utilizzando la parola chiavenew. Dichiarare un oggetto quindi è del tuttosimile a dichiarare un tipo di dato primitivo. Il"nome" che diamo ad un oggetto è detto"reference". Infatti, non sista parlando di una variabile tradizionale bensì di unpuntatore. Possiamo definire un puntatore come una variabileche contiene un indirizzo in memoria. C’è unasottile e potente differenza tra la dichiarazione di un tipodi dato primitivo ed uno non primitivo. Consideriamo ora unesempio, partendo dalla definizione di una classe che astraein 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 primitivoconsideriamo un double. Consideriamo le seguenti righedi codice, supponendo che si trovino all’interno di unmetodo main di un’altra classe:
double unNumero=5.0; Data unGiorno=new Data();
Graficamente potremmo immaginare la situazione in memoriacon questo tipo di schematizzazione:
La differenza pratica tra un reference ed una variabile,è evidente nelle assegnazioni. Consideriamo ilseguente frammento di codice:
double unNumero=5.0; double unAltroNumero=unNumero; Data unGiorno=new Data(); Data unAltroGiorno=unGiorno;
La variabile unAltroNumero, assumerà lostesso valore della variabile unNumero, ma, le duevariabili, rimarranno indipendenti l’unadall’altra. Infatti, il valore della variabileunNumero, sarà copiato nella variabileunAltroNumero. Se il valore di una delle due variabilisarà successivamente modificato, l’altravariabile non apporterà modifiche al propriovalore.
Invece, il reference unAltroGiorno, semplicementeassumerà il valore (cioè l’indirizzo) delreference unGiorno. Ciò significa cheunAltroGiorno punterà allo stesso oggetto cuipunta unGiorno. Ecco la situazione rappresentatagraficamente:
Quindi, se successivamente sarà apportata unaqualche modifica tramite uno dei due referenceall’oggetto comune, ovviamente questa saràverificabile anche tramite l’altro reference. Perintenderci:
unGiorno.anno
è sicuramente equivalente a:
unAltroGiorno.anno
- Passaggio di parametri per valore
Come abbiamo già accennato nel precedente capitoloil passaggio di parametri in Java avviene sempre per valore.Ciò significa che quando viene invocato un metodo checome parametro prende in input una variabile, al metodostesso viene passato solo il valore (una copia) dellavariabile, che quindi rimane immutata anche dopol'esecuzione del metodo. Per esempio consideriamo laclasse:
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
Stesso discorso vale per i tipi reference: viene semprepassato il valore del reference, ovvero, l'indirizzo inmemoria. 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() avessecambiato i valori delle variabili d'istanzadell'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, econtemporaneamente, si è certi che dopo la chiamatadel metodo il reference punti sempre allo stesso oggetto.
N.B.: altri linguaggi come il C, permettono anche ilpassaggio di parametri “per riferimento”. In quelcaso al metodo viene passato l'intero riferimento, nonsolo il suo indirizzo, con la conseguente possibilitàdi poter mutarne l'indirizzamento. Java ha scelto ancorauna volta la strada della robustezza e dellasemplicità, favorendola alla potenza dellinguaggio.