En Java, il y a toujours un mécanisme pass-by-value (passage par valeur), mais il y a une particularité pour les objets :
Ainsi, la modification des champs de l'objet à l'intérieur de la méthode se reflète sur l'objet original, tandis que la tentative d'assigner une nouvelle référence à une variable à l'intérieur de la méthode n'affecte pas l'objet original. Cela est souvent confondu avec le pass-by-reference, mais Java ne supporte pas le pass-by-reference !
Exemple :
void changePrimitive(int a) { a = 10; } void changeObject(Point p) { p.x = 10; } int num = 5; changePrimitive(num); // num est toujours 5 Point pt = new Point(1, 2); changeObject(pt); // maintenant pt.x == 10
Important ! Si à l'intérieur de la méthode on assigne p = new Point(100, 200), l'objet d'origine en dehors de la méthode ne changera pas. On modifie un champ de l'objet, pas sa référence !
Question : Peut-on changer un objet passé en argument, de sorte qu'en dehors de la méthode, la variable-référence pointe vers un nouvel objet ?
Réponse : Non, on ne peut pas. Lors de l'assignation d'une nouvelle référence à l'argument à l'intérieur de la méthode, cela ne concerne que la copie de la référence, qui disparaît après la sortie de la méthode. En dehors de la méthode, la variable-argument pointe toujours vers l'ancien objet.
void reassign(Point p) { p = new Point(100, 200); // uniquement localement ! } Point pt = new Point(5, 5); reassign(pt); // pt est toujours (5, 5)
Histoire
Dans un grand système financier, un API a été implémenté, qui "retournait" des modifications à un objet en modifiant la référence à l'intérieur de la méthode. En conséquence, après la sortie de la méthode, les modifications n'étaient pas reflétées. Il a fallu redessiner complètement une partie de la logique pour clairement distinguer la mutation et le retour de nouveaux objets.
Histoire
Lors de la tentative de réaliser un échange pour deux objets en Java avec la méthode
swap(A a, B b), le développeur passait des références et les échangeait à l'intérieur de la méthode. Cela n'a pas fonctionné. Il fallait soit retourner le résultat, soit utiliser des conteneurs-tableaux. L'ignorance du pass-by-value a conduit à un échange incorrect d'objets.
Histoire
Un des participants au projet a migré la logique depuis C++ et s'attendait à un comportement de pass-by-reference. En conséquence, les méthodes ont cessé de fonctionner correctement : les modifications à l'intérieur de la méthode ne "sortaient" pas. Il a fallu réécrire en urgence des parties critiques du code, ce qui a pris beaucoup de temps.