Java, i reference e la RAM

Questo è un argomento ostile, nel quale è facile perdersi, ma nello stesso tempo è la prima porta da aprire se si vuole entrare a pieno titolo nel mondo della programmazione java…

Innanzitutto distinguiamo tra reference value e object reference.
Un reference value rappresenta un valore (value) e precisamente il valore che viene restituto quando viene creato un particolare oggetto.
Un object reference (o semplicemnte reference) rappresenta invece una variabile che può memorizzare un reference value.
Questa differenza deve essere chiara perché altrimenti niente sarà mai chiaro con i reference in java!
Ora traduciamo questi concetti in codice.
Creiamo 2 object reference di tipo MiaClasse:

MiaClasse refOggetto1, refOggetto2;

Scrivendo questa riga di codice abbiamo comunicato a java di creare due variabili (nella RAM del calcolatore) di tipo MiaClasse e gli abbiamo anche detto che in queste 2 variabili DOVRANNO essere inseriti dei valori che si riferiranno (reference) a 2 oggetti di tipo MiaClasse. Stiamo parlando di “reference”! Questo significa che in queste 2 variabili java NON inserirà MAI gli oggetti veri e propri, ma il rifeimento a tali oggetti!!!
Rileggete bene l’ultimo paragrafo: è molto importante!

Bene. Inseriamo allora tali riferimenti ai 2 oggetti:

refOggetto1 = new MiaClasse(1);
refOggetto2 = new MiaClasse(2);

A questo punto java assegna un valore a refOggetto1 e un altro valore a refOggetto2. Ribadisco ancora che tale valore NON indica l’oggetto vero e proprio, ma indica la posizione (in RAM) dell’oggetto; il suo “riferimento”.
Si può rappresentare graficamente quanto detto con la seguente figura (scusate la poca eleganza).

Oggetti in RAM

In questa figura c’è rappresentato tutto quello che bisogna sapere sui reference!

Perché i reference refOggetto1 e refOggetto2 hanno uno sfondo bicolore?
La risposta a questa domanda svelerà uno dei segreti di java…
Nei reference non viene inserito soltanto l’indirizzo di memoria in cui è memorizzato l’oggetto, ma anche l’intervallo di memoria che sarà occupato dall’oggetto!
Quindi è come se nella parte verde chiaro ci fosse scritto l’indirizzo RAM dove “inizia” l’oggetto che ci interessa, mentre nella parte verde scuro fosse indicato lo spazio da sommare al punto iniziale per contenere l’oggetto.
Vi siete mai chiesti perché scrivere:

System.out.println(MiaClasse.toString());

procuri un output simile al seguente?

MiaClasse@c3c749

La @ è il separatore tra la parte verde chiaro e quella verde scuro!

Ora comprendere a fondo questo concetto sarà di fondamentale importanza quando parleremo di polimorfismo e di metodi virtuali!

In java NON avremo mai a che fare con gli oggetti veri e propri (indicati con lo sfondo rosa nella figura), ma solo con i loro riferimenti (sfondo verde).
Ecco perché quando noi scriviamo:

refOggetto2 = refOggetto1;

NON stiamo rendendo uguali gli oggetti e in realtà non stiamo rendendo uguali neanche i reference, ma solo una parte dei reference, cioè la parte che indica dove inizia l’oggetto in memoria.
Questo significa che dopo tale istruzione refOggetto2 punterà allo stesso indirizzo di memoria a cui punta refOggetto1 e quindi se noi apportiamo una modifica all’oggetto puntato da refOggetto2 la ritroviamo anche sull’oggetto puntato da refOggetto1; per forza! Entrambi puntano allo stesso oggetto!
Uguagliare 2 reference
L’oggetto a cui puntava refOggetto2 rimarrà in memoria fino a quando java, tramite il suo garbage collector, non si accorgerà che nessuno lo “cerca” e lo eliminerà.

Ma tutto quanto detto è valido solo e soltanto se i 2 reference sono stati dichiarati dello stesso tipo (come nel nostro caso)!
Se invece avessimo scritto:

MiaClasse refOggetto1;
MiaClasse2 refOggetto2;

e se non ci fosse legame tra le 2 classi, scrivere:

refOggetto2 = refOggetto1;

produrrebbe un errore in compilazione!

Abbiamo già visto che con i dati primitivi le cose funzionano ben diversamente, ma vi rimando ai relativi post.
I dati primitivi
Il passaggio dei parametri
Gli argomenti sono strettamente collegati.
Per “evolvere” il pensiero invece, è bene leggere questo post: java il polomorfismo e i metodi virtuali.
Mal di testa? E’ normale… passerà!

Hai letto questi articoli?