Java è passato per valore, non per riferimento

Introduzione

Molti programmatori Java si chiedono se Java utilizzi il passaggio per valore o il passaggio per riferimento. Questo articolo riassume il motivo per cui Java è sempre basato sul passaggio per valore.

Per prima cosa, cosa significa passaggio per valore e passaggio per riferimento?

  • Passaggio per valore: I valori dei parametri del metodo vengono copiati in un’altra variabile e poi l’oggetto copiato viene passato al metodo. Il metodo utilizza la copia.
  • Passaggio per riferimento: Un alias o riferimento al parametro effettivo viene passato al metodo. Il metodo accede al parametro effettivo.

Spesso, la confusione su questi termini è il risultato del concetto di riferimento dell’oggetto in Java. Tecnicamente, Java è sempre basato sul passaggio per valore, perché anche se una variabile potrebbe contenere un riferimento a un oggetto, quel riferimento dell’oggetto è un valore che rappresenta la posizione dell’oggetto in memoria. I riferimenti agli oggetti vengono quindi passati per valore.

Sia i tipi di dati di riferimento che i tipi di dati primitivi vengono passati per valore. Per saperne di più sui tipi di dati in Java.

Oltre a comprendere i tipi di dati, è anche importante capire l’allocazione di memoria in Java, perché i tipi di dati di riferimento e i tipi di dati primitivi sono memorizzati in modo diverso.

Dimostrazione del passaggio per valore

L’esempio seguente mostra come vengono passati i valori in Java.

Il programma di esempio utilizza la seguente classe:

public class Balloon {

	private String color;

	public Balloon() {}
	
	public Balloon(String c) {
		this.color = c;
	}
	
	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}
}

Il programma di esempio seguente utilizza un metodo generico, swap(), che scambia due variabili. Un altro metodo, changeValue(), tenta di modificare i valori delle variabili.

public class Test {

	public static void main(String[] args) {

		Balloon red = new Balloon("Red"); // riferimento di memoria = 50
		Balloon blue = new Balloon("Blue"); // riferimento di memoria = 100
		
		swap(red, blue);
		System.out.println("After the swap method executes:");
		System.out.println("`red` color value = " + red.getColor());
		System.out.println("`blue` color value = " + blue.getColor());
		
		changeValue(blue);
		System.out.println("After the changeValue method executes:");
		System.out.println("`blue` color value = " + blue.getColor());
		
	}

	// Metodo di scambio generico
	public static void swap(Object o1, Object o2){
		Object temp = o1;
		o1 = o2;
		o2 = temp;
	}

	private static void changeValue(Balloon balloon) { // palloncino = 100
		balloon.setColor("Red"); // palloncino = 100
		balloon = new Balloon("Green"); // palloncino = 200
		balloon.setColor("Blue"); // palloncino = 200
	}

}

Quando si esegue il programma di esempio, si ottiene il seguente output:

Output
After the swap method executes: 'red' color value = Red 'blue' color value = Blue After the changeValue method executes: 'blue' color value = Red

L’output mostra che il metodo swap() non ha scambiato i valori dei colori degli oggetti originali. Ciò aiuta a dimostrare che Java è basato sul passaggio per valore, poiché il metodo swap() agisce solo sulle copie dei valori di riferimento degli oggetti originali.

Questo test del metodo swap() può essere utilizzato con qualsiasi linguaggio di programmazione per verificare se si tratta di un passaggio per valore o per riferimento.

Esempio del Metodo swap() Spiegato

Quando si utilizza l’operatore new per creare un’istanza di una classe, l’oggetto viene creato e la variabile contiene la posizione in memoria in cui l’oggetto è salvato.

Balloon red = new Balloon("Red");
Balloon blue = new Balloon("Blue");

Ecco una suddivisione passo dopo passo di ciò che accade quando il metodo swap() viene eseguito:

  • Supponiamo che red punti alla posizione di memoria 50 e blue punti alla posizione di memoria 100, e che queste siano le posizioni di memoria di entrambi gli oggetti Balloon.

  • Quando la classe chiama il metodo swap() con le variabili red e blue come argomenti, vengono create due nuove variabili di oggetto, o1 e o2. Anche o1 e o2 puntano alle posizioni di memoria 50 e 100 rispettivamente.

  • Il seguente frammento di codice spiega cosa accade all’interno del metodo swap():

    public static void swap(Object o1, Object o2) { // o1 = 50, o2 = 100
    	Object temp = o1; // assegna il valore di riferimento dell'oggetto di o1 a temp: temp = 50, o1 = 50, o2 = 100
    	o1 = o2; // assegna il valore di riferimento dell'oggetto di o2 a o1: temp = 50, o1 = 100, o2 = 100
    	o2 = temp; // assegna il valore di riferimento di temp a o2: temp = 50, o1 = 100, o2 = 50
    } // termine del metodo
    
  • I valori di o1 e o2 sono scambiati, ma poiché i valori sono copie delle posizioni di memoria di red e blue, non ci sono modifiche ai valori dei colori red e blue.

Dato che le variabili contengono il riferimento agli oggetti, è un errore comune assumere di passare il riferimento e che Java passi per riferimento. Tuttavia, si passa un valore che è una copia del riferimento e quindi si passa per valore.

Il Metodo di Esempio changeValue() Spiegato

Il metodo successivo nell’esempio del programma cambia il valore del colore dell’oggetto referenziato dalla variabile blue:

private static void changeValue(Balloon balloon) { // palloncino = 100
	balloon.setColor("Red"); // palloncino = 100
	balloon = new Balloon("Green"); // palloncino = 200
	balloon.setColor("Blue"); // palloncino = 200
}

Ecco una spiegazione passo passo di cosa succede all’interno del metodo changeValue():

  • La classe chiama il metodo changeValue() sulla variabile blue che fa riferimento alla posizione di memoria 100. La prima riga crea un riferimento che punta anche alla posizione di memoria 100. Il valore del colore dell’oggetto nella posizione di memoria 100 viene cambiato in "Rosso".

  • La seconda riga crea un nuovo oggetto (con valore di colore "Verde"). Il nuovo oggetto si trova nella posizione di memoria 200. Eventuali metodi ulteriori eseguiti sulla variabile palloncino agiscono sull’oggetto nella posizione di memoria 200, e non influenzano l’oggetto nella posizione di memoria 100. La nuova variabile palloncino sovrascrive il riferimento creato nella riga 1 e il riferimento a palloncino dalla riga 1 non è più accessibile all’interno di questo metodo.

  • La terza riga cambia il valore del colore del nuovo oggetto Balloon nella posizione di memoria 200 in "Blue", ma non influisce sull’oggetto originale referenziato da blue nella posizione di memoria 100. Questo spiega perché l’ultima riga dell’output del programma di esempio stampa blue color value = Red, che riflette il cambiamento dalla riga 1.

Conclusione

In questo articolo hai appreso perché Java è passato per valore. Continua il tuo apprendimento con altri tutorial Java.

Source:
https://www.digitalocean.com/community/tutorials/java-is-pass-by-value-and-not-pass-by-reference