Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet
vabbè ci devo ragionare un po' su.![]()
Sperando di chiarirti le idee: qui non hai due oggetti! Ne hai solo uno e dopo la seconda riga, hai due variabili reference con lo stesso valore, ovvero fanno riferimento entrambe allo stesso oggetto.
Se successivamente assegni qualcos'altro (es. un altro nuovo oggetto Data) ad una delle due variabili, l'altra variabile non cambia e continua a fare riferimento all'oggetto Data creato alla prima riga.
Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet
Quindi, con l'istruzione
io ho dichiarato prima una variabile e successivamente ho istanziato un oggetto. In questo modo la variabile punterà alla locazione di memoria dove si trova oggetto1, in poche parole conterrà l'indirizzo di memoria dove si trova oggetto1.codice:Data oggetto1 = new Data();
Con l'istruzione
vado a dichiarare una seconda variabile ma anzichè farla puntare ad una locazione di memoria di un nuovo oggetto (questo non avviene perchè non c'è new Data()) le passo l'indirizzo di memoria dove si trova l'oggetto1 creato in precedenza.codice:Data oggetto2 = oggetto1;
Quindi ci sono due variabili (oggetto1 e oggetto2) che contengono lo stesso indirizzo di memoria e a quell'indirizzo di memoria si trova l'oggetto oggetto1.
Se poi ci fosse una terza riga di codice del tipo
vorrebbe dire che abbiamo fatto in modo ora che la seconda variabile non punti più alla locazione di memoria dove si trova oggetto1 ma è stato creato un nuovo oggetto e che quindi la seconda variabile punta alla locazione di memoria del nuovo oggetto.codice:Data oggetto2 = new Data();
E' corretto?
"Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza
Vediamo se ho capito anche il resto. Torniamo all'esempio che ho inserito nel post #5.
Quindi con
è come se dicessi "prendi la variabile dataDiNascita che contiene l'indirizzo di memoria dove si trova l'oggetto e che quindi contiene i campi giorno, mese e anno con già i valori all'interno inseriti nelle righe precedenti".codice:ogg.cambiaReference(dataDiNascita)
Tra l'altro il senso del metodo cambiaReference è appunto quello di cambiare il valore (forse sarebbe corretto dire l'indirizzo di memoria) di ogg perchè fino a quel momento ogg è una variabile che contiene l'indirizzo di una locazione di memoria diversa da dataDiNascita visto che sono state fatte due istanziazioni differenti nelle prime due righe:
codice:CiProvoConIReference ogg = new CiProvoConIReference(); Data dataDiNascita = new Data();
successivamente con il blocco di codice
è come se dicessi "lascia perdere quella locazione di memoria, crea un nuovo oggetto in modo che la variabile ogg non contenga l'indirizzo di memoria dove si trova dataDiNascita ma l'indirizzo di memoria dove si trova un nuovo oggetto che è inizializzato con valori di default". Per questa ragione dataDiNascita contiene ancora i valori inseriti in precedenza.codice:public class CiProvoConIReference { public void cambiaReference(Data data) { data = new Data(); } }
E' corretto?
Quando passi un oggetto ad un metodo, stai passando una copia del valore del reference. Il metodo chiamato può cambiare lo "stato" dell'oggetto (tramite qualunque metodo setter setXYZ o con altro nome che va a modificare le variabili di istanza dell'oggetto) ma NON può cambiare il valore della variabile reference che ha il chiamante.
Con il tuo esempio in #5 il metodo cambiaReference NON può (non è proprio tecnicamente possibile) cambiare il valore di dataDiNascita che è locale e usabile solo nel contesto del chiamante.
Pertanto in un metodo andare ad assegnare subito qualcos'altro ad un parametro (in generale ma specialmente se "reference") senza usarlo prima .... praticamente non serve a nulla e non ha senso.
Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet
Ok, quindi diciamo che è un esempio fine a se stesso.
Ho svolto un esercizio su questo argomento (in realtà l'avevo già postato ma l'ho rifatto).
Questa è la traccia:
e questa è la mia soluzione:Creare una classe Risultato che dichiari una sola variabile d'istanza di tipo float e di nome risultato. Aggiungere eventuali metodi e costruttori utili. Creare una classe CambiaRisultato con un metodo public di nome cambiaRisultato() che prende in input un oggetto di tipo risultato e ne modifica la variabile interna risultato sommandola con un altro valore. Creare una classe con un metodo main() di nome TestRisultato che stampi la variabile risultato di un oggetto di tipo Risultato, prima e dopo che questo oggetto sia passato in input al metodo cambiaRisultato() di un oggetto di tipo CambiaRisultato.
codice:public class TestRisultato { public static void main(String args[]) { Risultato oggetto1 = new Risultato(); System.out.println(oggetto1.risultato); CambiaRisultato oggetto2 = new CambiaRisultato(); oggetto2.cambiaRisultato(oggetto1); System.out.println(oggetto1.risultato); } }codice:public class Risultato { public float risultato; public float somma() { risultato = risultato + 1; return(risultato); } }Ho fatto questo esempio perchè il metodo cambiaRisultato() va a modificare (tramite il metodo somma()) la variabile risultato dell'oggetto1 poichè l'oggetto1 viene passato in input quindi sa esattamente dove puntare, mentre non viene assolutamente modificato l'indirizzo di memoria (o reference) poichè non c'è un'istruzione del tipo oggetto = new Risultato().codice:public class CambiaRisultato { public void cambiaRisultato(Risultato oggetto) { oggetto.somma(); } }
Giusto?
Ultima modifica di newutente; 06-11-2014 a 12:53
Questo infatti è più sensato, perché il metodo somma è effettivamente in grado di modificare lo stato dell'oggetto Risultato.
Sì e ribadisco che se anche ci fosse in cambiaRisultato un oggetto = new Risultato(); quello che farebbe è semplicemente cambiare il valore del parametro che è di fatto una variabile locale del metodo, totalmente slegata da qualunque altra variabile anche del chiamante.
Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet
ok, capito.
grazie per la spiegazione.