In generale in tutti i linguaggi di programmazione il passaggio dei parametri nell’invocazione di un metodo può avvenire in due modi:

  • Passaggio per valore
  • Passaggio per riferimento

Nel passaggio dei parametri per VALORE o anche chiamato per copia viene fatta una copia e questa è passata al metodo.

Modifiche alla variabile passata, fatte all’interno del metodo non influenzano il valore della variabile del metodo chiamante.

Per esempio se io chiamo un metodo e passo a questo metodo una variabile pippo, utilizzando un passaggio per valore, se nel metodo modifico la variabile passata queste modifiche non influenzano il valore della variabile pippo che abbiamo nel metodo chiamante.

Va tenuto in considerazione che ogni metodo ha il proprio ambiente locale di esecuzione, quindi quando passiamo un parametro per valore, quest’ultimo verrà copiato dalle celle di memoria dell’ambiente di esecuzione del metodo chiamante alle celle di memoria dell’ambiente di esecuzione del metodo chiamato.

Questo concetto può sembrare complicato, però adesso lo spieghiamo con un esempio così sarà più chiaro:

Il metodo main chiama il metodo calcolaAreaRettangolo passando due parametri: base e altezza.

Il metodo quando terminerà la sua esecuzione ritornerà al metodo main un risultato che salveremo nella variabile area.

Capiamo come avviene questo passaggio dei parametri per valore.

Quando viene eseguito il programma, si avvia il metodo main che crea un suo ambiente locale di esecuzione (nell’animazione è l’area di colore verde) cioè un’area di memoria che il main utilizza per salvare tutte le variabili che gli servono per svolger il proprio compito.

Anche il metodo calcolaAreaRettangolo avrà un suo ambiente locale di esecuzione (nell’animazione colorato in rosso) che usa per creare le sue variabili che utilizzerà per calcolare l’area di un rettangolo.

Nel momento in cui il main chiama il metodo calcolaAreaRettangolo e gli passa i due parametri base e altezza per valore il contenuto di queste due varibili vengono copiate all’interno delle due variabili a e b che si trovano nell’ambiente locale di esecuzione del metodo calcolaAreaRettangolo.

Quando il metodo calcolaAreaRettangolo termina la sua elaborazione, il risultato dell’elaborazione si troverà all’interno della variabile result. Questa variabile result però si trova nell’ambiente di esecuzione del metodo calcolaAreaRettangolo.

Per rendere disponibili il risultato dell’elaborazione dal metodo al main il valore della variabile result viene copiata all’interno della variabile area che si trova nell’ambiente di esecuzione del main.

PASSAGGIO DEI PARAMETRI PER RIFERIMENTO

Nel passaggio dei parametri per riferimento, invece di fare una copia dei parametri nell’ambiente locale del metodo chiamato, si passano gli indirizzi delle celle di memoria dell’ambiente globale che contengono i parametri.

Se per esempio l’area di memoria del nostro programma è rappresentata da questa scacchiera disegnata qui di seguito:

dove ogni quadratino di questa scacchiera è una cella di memoria e rappresenta un posto dove possiamo memorizzare un dato.

Ogni cella di memoria ha un indirizzo. Questo indirizzo serve per accedere ai dati salvati in memoria.

Per esempio se andiamo a salvare all’indirizzo 1040 la variabile nome avremo:

Indirizzo(nome) = 1040               

nome = Roberto

Quindi all’indirizzo 1040 si troverà salvato il valore Roberto.

Se al metodo chiamato viene passato l’indirizzo della cella di memoria della variabile allora il metodo accederà direttamente al valore originale della variabile e non alla sua copia.

Quindi questo comporta che le modifiche che verranno fatte dal metodo a quella variabile avverranno direttamente nella locazione di memoria originale.

Riassumendo

Passando i parametri per valore non si ha la modifica dei loro valori al termine della chiamata del metodo.

Questo perché viene fatta una copia dei parametri attuali nell’ambiente locale del metodo chiamato.

Se invece volessimo che i parametri passati subiscano modifiche dal metodo chiamato viene utilizzato il meccanismo del passaggio dei parametri per riferimento o indirizzo.

Perciò se passiamo come parametro ad un metodo l’indirizzo della variabile, in questo caso non opero su una copia ma sulla cella di memoria originale. Una modifica del parametro passato per riferimento al metodo chiamato cambia il valore della variabile nel metodo chiamante.

Quello che abbiamo visto finora sono le due modalità esistenti di passaggio di parametri che possono essere presenti nei linguaggi di programmazione.

Adesso vediamo in Java come avviene il passaggio dei parametri.

Prima di spiegare il passaggio dei parametri in Java va fatta una premessa.

In Java ogni valore può essere salvato in una variabile che poi viene passato ad un metodo.

In Java, ogni valore può essere un Oggetto o un tipo primitivo. I tipi primitivi sono numeri (come int, double e gli altri tipi numerici), char (caratteri) o boolean.

C’è una differenza fondamentale tra tipi primitivi e Oggetti in Java: le variabili di un tipo primitivo contengono valori, mentre le variabili oggetto non contengono oggetti, ma riferimenti ad oggetti. Per riferimento all’oggetto si intende l’indirizzo alla cella di memoria dell’oggetto.

Tu dirai a cosa mi serve sapere questa differenza??

Puoi apprezzare questa differenza quando fai la copia di una variabile.

Quando copi un valore di un tipo primitivo, l’originale e la copia del numero sono valori indipendenti, ma quando copi un riferimento ad un oggetto, sia l’originale che la copia si riferiscono allo stesso oggetto.

Ora ti chiederai perché mi stai dicendo tutto questo per spiegarmi il passaggio di riferimento in Java.

Te lo svelo subito…seguimi…

In Java il passaggio dei parametri avviene solo per valore. Quindi nessuna modifica nel metodo sui parametri formali cambierà i valori dei parametri attuali passati come argomento.

Però quando passiamo come parametri array o oggetti implicitamente java passerà al metodo una COPIA ma del loro RIFERIMENTO quindi di conseguenza sostanzialmente avverrà un passaggio per riferimento.

Quindi in questo caso le eventuali modifiche verranno effettuate nell’area di memoria globale che contiene l’array o l’oggetto.

Facciamo un esempio pratico:

In questo esempio viene passata la variabile var1 al metodo cambiaValore che cambierà il valore a 45 dopo di che il main stampa a video il valore della variabile var1.

Siccome in java il passaggio di parametri è per copia ed essendo var1 un tipo primitivo intero, la variabile var1 che si trova nel main non verrà modificata dal metodo cambiaValore e verrà stampato a video il valore 18 che è quello settato all’interno del metodo main.

Ora vediamo però cosa succede con le Stringhe.

Le Stringhe in Java sono degli “oggetti particolari” perciò si comportano in maniera differente. 😊

Se prendiamo lo stesso esempio precedente però al posto di int usiamo una variabile di tipo String:

essendo String un’oggetto per come spiegato poche righe sopra dovremmo aspettarci come comportamento un passaggio per riferimento.

Cioè passando al metodo cambiaValore la stringa “Ciao” e modificandola all’interno del metodo con il valore “Hello” ci si aspetta che l’output stampato a video sia “Hello”.

E invece NO!

L’output di questo programma è “Ciao”.

Quindi lo stesso comportamento del passaggio dei parametri per valore.

Come Mai???

La motivazione è abbastanza semplice. Te lo spiego subito.

Innanzi tutto devi conoscere un concetto fondamentale delle stringhe di Java: in Java le stringhe sono oggetti immutabili, cioè il loro valore non può essere cambiato dopo la loro creazione.

L’immutabilità dell’oggetto String deve essere sempre tenuta presente, altrimenti si rischia di cadere in errori del genere:

L’output di questo frammento di codice è “Arcobaleno” semplicemente perché il risultato dell’operazione substring non è utilizzato. Per utilizzarlo potremmo assegnare il nuovo oggetto (di tipo string) ritornato dal metodo substring alla stessa variabile di nome testo:

Questo genererà un output uguale a “Arc”.

Ma questo significa abbandonare l’oggetto precedente puntato dalla variabile testo.

In altre parole avremo nella memoria questa situazione:

In memoria la variabile testo non punterà più all’oggetto in memoria “Arcobaleno” ma al nuovo oggetto “Arc” e l’oggetto “Arcobaleno” sarà abbandonato a sé stesso senza riferimenti (e sarà preda del Garbage Collector che lo eliminerà dalla memoria… ma questo è un altro argomento 😊).

Cosa simile avviene quando passiamo una stringa come parametro ad un metodo.

Riprendendo l’esempio inserito sopra:

Siccome in Java le stringhe sono oggetti immutabili al momento della chiamata al metodo avremo questa situazione:

Quando viene chiamato il metodo cambiaValore il parametro var (variabile locale del metodo) punterà al riferimento della variabile var dichiarata nel metodo main, quindi allo stesso oggetto.

Quando però all’interno del metodo si modifica il valore della variabile var, essendo le stringhe in Java oggetti immutabili, verrà creato un nuovo oggetto string con il valore “Hello” che sarà puntato dalla variabile locale var del metodo cambiaValore.

Di conseguenza puntando questa nuova variabile si perderà il riferimento alla vecchia variabile “Ciao” che rimarrà puntata solo dalla variabile var del main.

Ecco spiegato perché la stampa in output della variabile var all’interno del main stamperà “Ciao”.

 

P.S. Se vuoi accedere al mio Corso GRATUITO dove ti spiego anche con semplicità tutte le fasi che ti permettono di sviluppare qualsiasi tipologia di software e come diventare un programmatore professionista anche se parti da zero allora CLICCA QUI

P.P.S. Se ti è piaciuto questo articolo lascia un commento qui sotto e clicca MI PIACE e CONDIVIDI sulla mia pagina Facebook per avere futuri aggiornamenti.