162 votes

Concaténation de chaînes de caractères nulles en Java

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"

182voto

Mark Peters Points 42201

Pourquoi doit ça marche ?

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.

Comment Est-ce que ça marche ?

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 .

25voto

Jonathon Faust Points 7543

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.

12voto

Roland Illig Points 15357

La deuxième ligne est transformée en le code suivant :

s = (new StringBuilder()).append((String)null).append("hello").toString();

Les méthodes append peuvent gérer null arguments.

10voto

krico Points 2368

Vous n'utilisez pas le "null" et vous n'obtenez donc pas l'exception. Si vous voulez le NullPointer, faites simplement

String s = null;
s = s.toString() + "hello";

Et je pense que ce que tu veux faire c'est :

String s = "";
s = s + "hello";

7voto

birryree Points 29165

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.com

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.

Powered by:

X