web-dev-qa-db-fra.com

Valeurs NULL de Strings et Integers en Java

public class Test {
    public static void main(String[] args) {

        String s = null;
        String s1 = null;
        Integer i = null;
        Integer i1 = null;

        System.out.println(s+i);
        System.out.println(i+s);
        System.out.println(s+s1);

        try {
            System.out.println(i+i1);
        } catch (NullPointerException np) {         
            System.out.print("NullPointerException");       
        }
    }

}

La question est simple: pourquoi reçois-je une NullPointerException uniquement à la dernière ligne?

49
tania

Votre code utilise deux opérateurs différents - additifs . Les trois premières lignes utilisent chaîne de concaténation , tandis que la dernière utilise addition numérique .

La concaténation de chaînes est bien définie pour transformer null en "null" :

  • Si la référence est null, elle est convertie en chaîne "null" (quatre ASCII caractères n, u, l, l).

Il n'y a donc pas de NPE.

Ajouter deux objets Integer ensemble nécessite qu'ils soient unboxed . Cela entraîne le déréférencement de la référence null, ce qui conduit au NPE:

  • Si r est null, la conversion unboxing génère une NullPointerException
60
NPE

Notez que les trois premières utilisations de l'opérateur + impliquent une concaténation de chaînes. Seul le dernier correspond au nombre réel somme . Lorsque la concaténation de chaînes est impliquée (où la variable s est impliquée), le compilateur Java utilise une astuce intelligente pour améliorer les performances. Il remplace l'opérateur + par StringBuilder. Par exemple, votre première ligne est traduite en:

StringBuilder tmp = new StringBuilder();
tmp.append(s);
tmp.append(i);
System.out.println(tmp);

StringBuilder est null- friendly donc, peu importe ce que vous transmettez comme argument, il le remplace joliment par "null" chaîne.

La situation est différente à la dernière ligne. Là, vous faites référence à deux objets Integer. La seule chose que la JVM puisse faire ici est de les déballer (i.intValue()) et d’effectuer le calcul proprement dit. Unboxing de null cause NullPointerException.

17
Tomasz Nurkiewicz

La concaténation (opérateur +) de tout ce qui a un Stringaboutit à un Stringname__. Chaque opérande est d'abord converti en chaîne (à l'aide de toString() ou de la valeur "null"), puis concaténé.

Mais la dernière opération implique uniquement Integername__s, de sorte que les règles précédentes ne s'appliquent pas. Au lieu d'une concaténation, il s'agit d'une addition. Mais pour ajouter deux Integername__s, il convertit les objets (Integername__s) en valeurs primitives (int), ce qui n'est pas possible si Integerest null. C'est pourquoi vous obtenez un NullPointerExceptionname__.

5
Bastien Jansen

Semble être un cas d'auto-déballage. Si vous avez deux Integers first et second, le résultat de leur addition sera first.intValue() + second.intValue(). Étant donné que les deux sont nuls, il en résulte un NPE.

1
Makoto

Il convient de noter que la réponse à cette question aurait dû être évidente:

C:\Temp>Java Test
nullnull
nullnull
nullnull
NullPointerException
0
djangofan

Jetez un coup d'œil au bytecode pour votre programme. Vous remarquerez que votre objet null est transmis en tant que paramètre à la méthode PrintStream.print (). Le code source de la méthode print () utilise String.valueOf () comme indiqué ci-dessous:

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}
0
ziggy