Pourquoi ce qui suit fonctionne-t-il ? Je m'attendrais à ce qu'un NullPointerException
pour être jeté.
String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"
Pourquoi ce qui suit fonctionne-t-il ? Je m'attendrais à ce qu'un NullPointerException
pour être jeté.
String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"
Le site JLS 5, section 15.18.1.1 JLS 8 § 15.18.1 " Opérateur de concaténation de chaînes de caractères + ". ce qui conduit à JLS 8, § 5.1.11 " Conversion des chaînes de caractères ". exige que cette opération réussisse sans échec :
...Désormais, seules les valeurs de référence doivent être prises en compte. Si la référence est nulle, elle est convertie en la chaîne "null". (quatre caractères ASCII n, u, l, l). Sinon, la conversion est effectuée comme si elle était effectuée par une invocation de la méthode toString de l'objet référencé sans arguments ; mais si le résultat de l'invocation de la méthode toString est nul, la chaîne "null" est utilisée à la place.
Regardons le bytecode ! Le compilateur prend votre code :
String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"
et le compile en bytecode comme si vous aviez écrit ceci :
String s = null;
s = new StringBuilder(String.valueOf(s)).append("hello").toString();
System.out.println(s); // prints "nullhello"
(Vous pouvez le faire vous-même en utilisant javap -c
)
Les méthodes append de StringBuilder
tous gèrent très bien la nullité. Dans ce cas, parce que null
est le premier argument, String.valueOf()
est invoqué à la place puisque StringBuilder n'a pas de constructeur qui prend un type de référence arbitraire.
Si vous aviez fait s = "hello" + s
à la place, le code équivalent serait :
s = new StringBuilder("hello").append(s).toString();
où, dans ce cas, la méthode append prend le null et le puis le délègue à String.valueOf()
.
Nota: La concaténation de chaînes de caractères est en fait l'un des rares endroits où le compilateur peut décider de la ou des optimisations à effectuer. En tant que tel, le code "équivalent exact" peut différer d'un compilateur à l'autre. Cette optimisation est autorisée par JLS, section 15.18.1.2 :
Pour améliorer les performances de la concaténation répétée de chaînes de caractères, un compilateur Java peut utiliser la classe StringBuffer ou une technique similaire pour réduire le nombre d'objets String intermédiaires créés par l'évaluation d'une expression.
Le compilateur que j'ai utilisé pour déterminer le "code équivalent" ci-dessus était le compilateur d'Eclipse, ecj .
Voir la section 5.4 y 15.18 de la spécification du langage Java :
La conversion des chaînes ne s'applique qu'aux opérandes de l'opérateur binaire + lorsque l'un des arguments est une chaîne de caractères. Dans Dans ce seul cas particulier, l'autre de l'opérateur + est converti en une String, et une nouvelle chaîne, qui est la concaténation des deux chaînes de caractères est le résultat du +. La conversion des chaînes de caractères est spécifiée en détail dans la section description de l'opérateur de concaténation + de chaînes de caractères.
y
Si une seule expression d'opérande est de type String, la conversion en chaîne de caractères est effectuée sur l'autre opérande pour pour produire une chaîne de caractères au moment de l'exécution. Le résultat de résultat est une référence à un objet String (nouvellement créé, sauf si l'expression soit une expression constante au moment de la compilation compilation (§15.28))qui est la concaténation des deux chaînes chaînes de caractères. Les caractères de l'opérande l'opérande de gauche précèdent les caractères de l'opérande de droite dans la chaîne nouvellement créée. Si un de type String est null, alors la chaîne "null" est utilisée à la place de cet opérande.
Il s'agit d'un comportement spécifié dans l'API de Java. String.valueOf(Object)
méthode. Quand vous faites une concaténation, valueOf
est utilisé pour obtenir le String
représentation. Il existe un cas particulier si l'Objet est null
dans ce cas, la chaîne "null"
est utilisé.
public static String valueOf(Object obj)
Renvoie la représentation de la chaîne de caractères de l'argument Objet.
Paramètres : obj - un objet.
Les retours :
si l'argument est null, alors une chaîne égale à "null" ; sinon, la valeur de obj.toString() est retournée.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.