Contrairement à certains termes courants, Java passe tout par valeur. Même lorsque nous travaillons avec des objets, ce que nous passons en réalité est la valeur de la référence à l’objet, pas l’objet lui-même.
Références en Java, des pointeurs déguisés
Considérons la déclaration :
d = new Dog("Fifi");
Il est crucial de comprendre que myDog
n’est pas un objet Dog
; c’est essentiellement un pointeur vers un Dog
. Cela signifie que lorsque vous créez un objet :
Dog myDog = new Dog("Rover");
Vous passez en réalité l’adresse du nouvel objet Dog
à toute méthode prenant myDog
en paramètre. Bien que les pointeurs Java ne représentent pas directement les adresses mémoire, les considérer de cette manière simplifie la compréhension.
Explorons un exemple de méthode :
public class TestObject{
public static void main(String ... args) {
Dog myDog = new Dog("Rover");
foo(myDog);
System.out.println(myDog.getName());//5
}
public void foo(Dog someDog) { // 1
someDog.setName("Max"); // 2
someDog = new Dog("Fifi"); // 3
someDog.setName("Rowlf"); // 4
}
}
- À la ligne 1,
someDog
est défini sur la valeur 3333 (en supposant que l’objetmyDog
est à l’adresse mémoire 3333). - À la ligne 2,
someDog
est suivi jusqu’auDog
qu’il pointe (l’objetDog
à l’adresse 3333), et ceDog
est invité à changer son nom en “Max”. - À la ligne 3, un nouveau
Dog
est créé à l’adresse 4444, etsomeDog
est maintenant assigné à cette adresse (4444). - À la ligne 4,
someDog
est suivi jusqu’auDog
qu’il pointe (l’objetDog
à l’adresse 4444), et ceDog
est invité à changer son nom en “Rowlf”.
Maintenant, considérons ce qui se passe en dehors de la méthode : La question est, myDog
a-t-il changé ?
La réponse réside dans le fait de se rappeler que myDog
est un pointeur, pas l’objet Dog
lui-même. La réponse est NON. myDog
a toujours la valeur 3333 ; il pointe toujours vers l’objet Dog
d’origine.
A la ligne 5, c’est donc bien “Max” qui sera affiché comme nom de chien.
Pour approfondir ce sujet je vous invite à consulter cet article.
Considerons l’exemple ci dessous :
Que se passe t-il si on affecte une référence null à un paramètre?
public class TestObject{
public static void main(String ... args) {
Dog myDog = new Dog("Rover");
foo(myDog);
System.out.println(myDog.getName());
}
public void foo(Dog someDog) {//1
someDog = null;//2
}
}
Cet exemple est très similaire au précedent. Je vous epargne l’explication des différentes étapes.
A votre avis quel resultat produira ce code?
D’aucun serait tenté de dire que ce code produira une exception de type NullpointerException. En réalité il n’en est rien.
Souvenez vous someDog
est défini sur une valeur precise (par exemple 3333). La méthode foo ne modifie pas someDog
.
En effet à la ligne //1 someDog
et myDog
pointe tous les deux sur l’adresse 3333.
A la ligne //2, nous faisons pointer someDog
sur la reference nulle (une variable special en java). Mais myDog
pointe toujours sur 3333.