Concaténation de chaînes null en Java

Pourquoi le suivant fonctionne-t-il? Je m’attendrais à ce qu’une NullPointerException soit lancée.

 Ssortingng s = null; s = s + "hello"; System.out.println(s); // prints "nullhello" 

Pourquoi ça doit marcher?

Le JLS 5, Section 15.18.1.1 JLS 8 § 15.18.1 “Opérateur de concaténation de chaînes +” , menant au JLS 8, § 5.1.11 “Conversion de chaînes” , exige que cette opération aboutisse sans échec:

… Maintenant, seules les valeurs de référence doivent être sockets en compte. Si la référence est null, elle est convertie en la chaîne “null” (quatre caractères ASCII n, u, l, l). Sinon, la conversion est effectuée comme par une invocation de la méthode toSsortingng de l’object référencé sans arguments; mais si le résultat de l’invocation de la méthode toSsortingng est null, la chaîne “null” est utilisée à la place.

Comment ça marche?

Regardons le bytecode! Le compilateur prend votre code:

 Ssortingng s = null; s = s + "hello"; System.out.println(s); // prints "nullhello" 

et le comstack en bytecode comme si vous aviez écrit ceci:

 Ssortingng s = null; s = new SsortingngBuilder(Ssortingng.valueOf(s)).append("hello").toSsortingng(); System.out.println(s); // prints "nullhello" 

(Vous pouvez le faire vous-même en utilisant javap -c )

Les méthodes append de SsortingngBuilder gèrent toutes les SsortingngBuilder nulles. Dans ce cas, parce que null est le premier argument, Ssortingng.valueOf() est invoqué à la place, car SsortingngBuilder ne possède pas de constructeur prenant un type de référence arbitraire.

Si vous aviez fait s = "hello" + s place, le code équivalent serait:

 s = new SsortingngBuilder("hello").append(s).toSsortingng(); 

où, dans ce cas, la méthode append prend la valeur null et la délègue ensuite à Ssortingng.valueOf() .

Remarque: La concaténation de chaînes est en fait l’un des rares endroits où le compilateur peut décider 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 augmenter les performances de la concaténation de chaînes répétée, un compilateur Java peut utiliser la classe SsortingngBuffer ou une technique similaire pour réduire le nombre d’objects Ssortingng 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 les sections 5.4 et 15.18 de la spécification du langage Java:

La conversion de chaîne s’applique uniquement aux opérandes de l’opérateur binary + lorsqu’un des arguments est une chaîne. Dans ce cas particulier, l’autre argument du + est converti en un Ssortingng, et un nouveau Ssortingng qui est la concaténation des deux chaînes est le résultat du +. La conversion de chaîne est spécifiée en détail dans la description de l’opérateur de concaténation de chaîne +.

et

Si une seule expression d’opérande est de type Ssortingng, la conversion de chaîne est effectuée sur l’autre opérande pour produire une chaîne au moment de l’exécution. Le résultat est une référence à un object Ssortingng (nouvellement créé, sauf si l’expression est une expression constante de compilation (§15.28)) qui est la concaténation des deux chaînes d’opérande. Les caractères de l’opérande gauche précèdent les caractères de l’opérande droit dans la chaîne nouvellement créée. Si un opérande de type Ssortingng est nul, la chaîne “null” est utilisée à la place de cet opérande.

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

 s = (new SsortingngBuilder()).append((Ssortingng)null).append("hello").toSsortingng(); 

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

Vous n’utilisez pas le “null” et vous ne recevez donc pas l’exception. Si vous voulez le NullPointer, faites simplement

 Ssortingng s = null; s = s.toSsortingng() + "hello"; 

Et je pense que ce que vous voulez faire est:

 Ssortingng s = ""; s = s + "hello"; 

C’est le comportement spécifié dans la méthode Ssortingng.valueOf(Object) API Java. Lorsque vous faites de la concaténation, valueOf est utilisé pour obtenir la représentation Ssortingng . Il y a un cas particulier si l’object est null , auquel cas la chaîne "null" est utilisée.

public static Ssortingng valueOf(Object obj)

Renvoie la représentation sous forme de chaîne de l’argument Object.

Paramètres: obj – un object.

Résultats:

si l’argument est nul, alors une chaîne égale à “null”; sinon, la valeur de obj.toSsortingng () est renvoyée.