Подтвердить что ты не робот

Нулевые значения строк и целых чисел в 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");       
        }
    }

}

Вопрос прост: почему я получаю NullPointerException только в последней строке?

4b9b3361

Ответ 1

В вашем коде используются два разных аддитивных оператора. В первых трех строках используется конкатенация строк, в то время как последняя использует числовое добавление.

Конкатенация строк четко определена, чтобы превратить null в "null":

  • Если ссылка null, она преобразуется в строку "null" (четыре символа ASCII n, u, l, l).

Следовательно, нет NPE.

Добавление двух объектов Integer вместе требует, чтобы они были unboxed. Это приводит к разрыву ссылки null, которая приводит к NPE:

  • Если r имеет значение null, то при распаковке преобразование выбрано NullPointerException

Ответ 2

Обратите внимание, что первые три оператора оператора + связаны с конкатенацией строк. Только последняя является фактической числовой суммой. Когда задействована конкатенация строк (где задействуется переменная s), компилятор Java использует некоторые умные трюки для повышения производительности. Он заменяет оператор + на StringBuilder. Например, ваша первая строка переведена на:

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

StringBuilder null - дружелюбно, поэтому независимо от того, что вы передаете в качестве аргумента, он красиво заменяет его строкой "null".

В последней строке ситуация различна. Там вы ссылаетесь на два объекта Integer. Единственное, что JVM может сделать здесь, это распаковать их (i.intValue()) и выполнить фактическое вычисление. Unboxing null вызывает NullPointerException.

Ответ 3

Конкатенация (оператор +) всего с String приводит к a String. Каждый операнд сначала преобразуется в String (либо используя toString(), либо используя значение "null"), затем конкатенируется.

Но последняя операция включает только Integer, поэтому предыдущие правила не применяются. Вместо конкатенации он делает дополнение. Но чтобы добавить два Integer s, он преобразует объекты (Integer s) в примитивные значения (int), что невозможно, если Integer равно null. Вот почему вы получаете NullPointerException.

Ответ 4

Кажется, это случай автоматической распаковки. Если у вас есть два Integer first и second, то результатом их добавления будет first.intValue() + second.intValue(). Поскольку оба они ноль, что приводит к NPE.

Ответ 5

Посмотрите на байт-код для вашей программы. Вы заметите, что ваш нулевой объект передается как параметр метода PrintStream.print(). Исходный код для метода print() использует String.valueOf(), как показано ниже:

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

Ответ 6

Следует отметить, что ответ на этот вопрос должен был быть очевиден на выходе:

C:\Temp>java Test
nullnull
nullnull
nullnull
NullPointerException