- Passage par Référence
En Java, le passage par référence (Reference Passing) désigne le mécanisme par lequel, lorsqu'une méthode reçoit une référence d'objet en paramètre, toute modification effectuée sur cet objet impacte l'original. Ce concept s'oppose au passage par valeur (Value Passing), qui se produit lors du transfert de types de données primitifs, où seule une copie de la valeur est transmise, laissant l'original inchangé.
Exemple de Passage par Référence
package com.demo.referencement;
/**
* Démonstration du passage par référence en Java
*/
public class PassageReference {
public static void main(String[] args) {
Utilisateur utilisateur = new Utilisateur("Jean");
System.out.println("Avant modification: " + utilisateur.getNom()); // Affiche Avant: Jean
modifierNom(utilisateur);
System.out.println("Après modification: " + utilisateur.getNom()); // Affiche Après: Pierre
}
public static void modifierNom(Utilisateur u) {
u.setNom("Pierre");
}
}
class Utilisateur {
private String nom;
public Utilisateur(String nom) {
this.nom = nom;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
}
Dans cet exemple, la méthode modifierNom reçoit une référence à un objet Utilisateur. Lorsque nous appelons u.setNom("Pierre"), nous modifions directement l'instance d'objet transmise à la méthode. Par conséquent, lorsque nous accédons à nouveau à l'objet utilisateur, son nom a été modifié en "Pierre". Cela illustre le concept de passage par référence : les modifications apportées via la référence affecetnt l'objet original.
- Différences entre Passage par Référence et Passage par Valeur
Passage par Valeur : Lorsque vous transmettez des types de données primitifs (comme int, double, char, etc.), c'est une copie de la valeur qui est passée à la méthode. Toute modification de cette copie n'affecte pas la valeur originale. Lors de l'appel de méthode, l'argument réel transmet une copie de son contenu au paramètre formel. Le paramètre formel reçoit ainsi une copie de la valeur de l'argument réel, de sorte que toute opération sur ce paramètre ne concerne que cette copie et n'affecte pas le contenu original. Le passage par valeur transmet une copie du contenu réel, les opérations sur la copie n'affectent pas l'original.
public static void main(String[] args) {
int valeur = 10;
System.out.println("Avant: " + valeur); // Affiche Avant: 10
augmenter(valeur); // Note: on transmet une copie de valeur, la valeur originale ne change pas
System.out.println("Après: " + valeur); // Affiche Après: 10
}
public static void augmenter(int nombre) {
nombre = nombre + 1; // On modifie ici la copie, pas la variable valeur originale
}
Passage par Référence : Lorsque vous transmettez des objets (toute instance de type non primitif), c'est la référence de l'objet (l'adresse mémoire) qui est passée à la méthode. Toute modification de l'objet affectera l'original. La "référence" est en fait l'adresse qui pointe vers le contenu réel. Lors de l'appel de méthode, l'adresse de l'argument réel est transmise au paramètre formel corrrespondant. Dans le corps de la méthode, le paramètre formel et l'argument réel pointent vers la même adresse mémoire, les opérations sur le paramètre affectent donc le contenu réel.
Résumé
Le passage par référence en Java concerne principalement le transfert de paramètres pour les objets et les tableaux. Lorsque vous devez modifier l'état ou les propriétés d'un objet, le passage par référence est très utile. Cependant, il est important de noter qu' même dans le cas d'un passage par référence, si vous tentez de modifier la direction de la référence d'objet (par exemple, en assignant la référence d'un objet à un nouvel objet), la référence originale externe ne changera pas pour pointer vers le nouvel objet, sauf si vous assignez explicitement le nouvel objet à la référence originale. Par exemple :
public static void modifierReference(Utilisateur u) {
u = new Utilisateur("Marc"); // Ceci n'affecte pas la référence originale 'utilisateur',
// qui pointe toujours vers l'objet original Jean
}
Dans ce cas, u dans la méthode modifierReference est redirigé vers une nouvelle instance Utilisateur, mais la variable utilisateur originale pointe toujours vers l'instance originale. Pour que la référence externe pointe également vers le nouvel objet, vous devriez procéder ainsi :
public static void modifierReference(Utilisateur u) {
Utilisateur nouveau = new Utilisateur("Marc"); // Ceci n'affecte pas la référence originale,
// sauf si nous faisons :
u = nouveau; // Ainsi la référence originale 'utilisateur' pointera aussi vers
// la nouvelle instance "Marc"
}
Conclusion
On peut donc conclure qu'en Java, tous les passages de paramètres, qu'il s'agisse de types primitifs ou de types de référence, se font par valeur, ou plus précisément par copie. La différence réside dans ce qui est copié :
Lors de l'opération sur des types de données primitifs, puisque le contenu original et la copie stockent tous deux la valeur réelle et se trouvent dans différentes zones de la pile, les opérations sur le paramètre formel n'affectent pas le contenu original.
Lors de l'opération sur des types de référence, il y a deux cas : soit le paramètre formel et l'argument réel pointent vers le même objet, auquel cas les opérations sur le paramètre affecteront le contenu de l'objet pointé par l'argument réel ; soit le paramètre formel est modifié pour pointer vers une nouvelle adresse d'objet (par réassignation de la référence), auquel cas les opérations sur le paramètre n'affecteornt pas le contenu de l'objet pointé par l'argument réel.
--