Passage des paramètres et comparaison d’objets #
Dans ce chapitre, nous allons expliquer la particularité du passage des paramètres par valeur pour comprendre pourquoi il faut être vigilant lorsque nous prêtons nos objets à des API tierces. Nous reviendrons également sur les dangers de la comparaison d’objets qui est une source d’erreurs courantes en Java.
Passage des paramètres par valeur #
En Java, le passage des paramètres se fait par valeur et non par référence : la valeur de l’argument est copiée. S’il s’agit d’un type primitif, une copie est réalisée et il est impossible de modifier sa référence.
|
|
Dans la méthode test
, i
a été copié. La modification n’a aucun impact pour l’appelant:
|
|
Pour les objets, il en est tout autre : c’est la référence qui est copiée. Prenons des objets mutables que nous connaissons:
void test(final StringBuilder str, final List<Integer> is) {
str.append("hacked!");
is.add(42);
}
...
StringBuilder dontTouchPlease = new StringBuilder();
List<Integer> emptyList = new ArrayList<>();
test(dontTouchPlease, emptyList);
// dontTouchPlease ==> "hacked!"
// emptyList ==> [42]
Dans la méthode test
, str
est une nouvelle référence copiée MAIS qui pointe sur le même objet en mémoire. Pareil pour is
. Si les objets sont mutables, il est donc possible de les modifier, même si les références sont finales.
De la même façon, l’opérateur d’affectation ne copie pas un objet, il copie sa référence:
|
|
Il s’agit d’un autre avantage de travailler avec des objets immutables. Une méthode qui prend un String
ne peut pas faire de dégâts puisque l’objet ne peut pas être modifié.
Conseil
Ne faites confiance à personne ! Soyez conservateur avec vos références. Si une API vous demande un objet mutable dont vous souhaitez garder la propriété, copiez-le ou transmettez une vue immutable de l’objet. Si votre API doit retourner un objet mutable dont vous souhaitez également garder la propriété, faites de même.
Ne faites confiance à personne avec des API tierces:
|
|
Pareil pour vos API. L’objet de a référence clients
vous appartient.
|
|
Conseil
Notez qu’il est possible de déclarer un argument
final
. Il s’agit même d’une bonne pratique.void test(final int i) { i = i + 1; // ne compile plus }
Nombre arbitraire d’arguments #
Une méthode peut comporter un nombre arbitraire d’arguments (entre 0 et une infinité). L’argument est considéré comme un tableau statique.
|
|
Utilisations possibles:
|
|
Comparaison #
Un piège fréquent est de comparer si deux objets sont égaux en utilisant l’opérateur ==
. Comme nous l’avons déjà vu, cet opérateur compare les références et non la structure d’un objet. Il s’agit d’une source de bugs récurrents comme le montre cet exemple sur des chaînes de caractères:
"HELLO" == "hello".toUpperCase(); // ==> false
"HELLO".equals( "hello".toUpperCase() ); // ==> true