Il meccanismo del Passaggio degli Argomenti in Java
- In Java, il meccanismo del passaggio degli argomenti può sembrare confuso, ma in realtà è piuttosto semplice.
- Java utilizza il passaggio per valore per tutti gli argomenti, ma l'effetto differisce a seconda che venga passato un tipo primitivo o un tipo riferimento.
- Quando si passa un tipo primitivo a un metodo, viene fatto un passaggio per valore, il che significa che le modifiche al parametro non influenzano l'argomento originale.
- Quando si passa un oggetto a un metodo, viene fatto un passaggio per riferimento, il che significa che le modifiche al parametro influenzano l'oggetto originale.
- È importante distinguere tra il passaggio per valore e il passaggio per riferimento, poiché influiscono sul comportamento dei metodi in Java.
Dettagli sul Passaggio degli Argomenti
In generale, ci sono due modi in cui un linguaggio di programmazione può passare un argomento a una subroutine (o metodo o funzione che dir si voglia).
-
Il primo modo è il passaggio per valore (call-by-value):
Questo approccio copia il valore di un argomento nel parametro formale della subroutine. Pertanto, le modifiche apportate al parametro della subroutine non hanno alcun effetto sull'argomento.
-
Il secondo modo in cui un argomento può essere passato è il passaggio per riferimento (call-by-reference):
In questo approccio, un riferimento a un argomento (non il valore dell'argomento) viene passato al parametro. All'interno della subroutine, questo riferimento viene utilizzato per accedere all'argomento effettivo specificato nella chiamata. Ciò significa che le modifiche apportate al parametro influenzeranno l'argomento utilizzato per chiamare la subroutine.
Come si vedrà, anche se Java utilizza il passaggio per valore per passare tutti gli argomenti, l'effetto preciso differisce a seconda che venga passato un tipo primitivo o un tipo riferimento.
Passaggio per Valore
Quando si passa un tipo primitivo a un metodo, questo viene passato per valore. Quindi, viene fatta una copia dell'argomento e ciò che accade al parametro che riceve l'argomento non ha effetto al di fuori del metodo. Ad esempio, si consideri il seguente programma:
// I tipi primitivi sono passati per valore.
class Test {
void metodo(int i, int j) {
i *= 2;
j /= 2;
}
}
class PassaggioPerValore {
public static void main(String[] args) {
Test oggetto = new Test();
int a = 15, b = 20;
System.out.println("a e b prima della chiamata: " +
a + " " + b);
oggetto.metodo(a, b);
System.out.println("a e b dopo la chiamata: " +
a + " " + b);
}
}
L'output di questo programma è il seguente:
a e b prima della chiamata: 15 20
a e b dopo la chiamata: 15 20
Come si può vedere, le operazioni che si verificano all'interno di metodo()
non hanno alcun effetto sui valori di a
e b
utilizzati nella chiamata; i loro valori non sono cambiati in 30 e 10.
Passaggio per Riferimento
Quando si passa un oggetto a un metodo, la situazione cambia drasticamente, poiché gli oggetti sono passati con ciò che è effettivamente un passaggio per riferimento.
Occorre tenere a mente che quando si crea una variabile di tipo classe, si sta solo creando un riferimento a un oggetto. Pertanto, quando si passa questo riferimento a un metodo, il parametro che lo riceve si riferirà allo stesso oggetto a cui si riferisce l'argomento.
Questo significa effettivamente che gli oggetti agiscono come se venissero passati ai metodi mediante passaggio per riferimento. Le modifiche all'oggetto all'interno del metodo influiscono sull'oggetto utilizzato come argomento. Ad esempio, si consideri il seguente programma:
// Gli oggetti sono passati tramite i loro riferimenti.
class Test {
int a, b;
Test(int i, int j) {
a = i;
b = j;
}
// passare un oggetto
void metodo(Test o) {
o.a *= 2;
o.b /= 2;
}
}
class PassaggioOggettoRif {
public static void main(String[] args) {
Test oggetto = new Test(15, 20);
System.out.println("oggetto.a e oggetto.b prima della chiamata: " +
oggetto.a + " " + oggetto.b);
oggetto.metodo(oggetto);
System.out.println("oggetto.a e oggetto.b dopo la chiamata: " +
oggetto.a + " " + oggetto.b);
}
}
Questo programma genera il seguente output:
oggetto.a e oggetto.b prima della chiamata: 15 20
oggetto.a e oggetto.b dopo la chiamata: 30 10
Come si può vedere, in questo caso, le azioni all'interno di metodo()
hanno influenzato l'oggetto utilizzato come argomento.
Differenza tra riferimento e valore
Quando un riferimento a oggetto è passato a un metodo, il riferimento stesso è passato usando il passaggio per valore. Tuttavia, poiché il valore passato fa riferimento a un oggetto, la copia di quel valore continuerà a riferirsi allo stesso oggetto a cui si riferisce l'argomento corrispondente.