Ответ 1
Это может помочь показать вам байт-код. Взгляните на следующий javap
вывод вашего класса:
> javap -classpath target\test-classes -c RefTest
Compiled from "RefTest.java"
public class RefTest extends java.lang.Object{
public RefTest();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: aconst_null
1: astore_1
2: aconst_null
3: astore_2
4: getstatic #17; //Field java/lang/System.out:Ljava/io/PrintStream;
7: aload_1
8: invokevirtual #23; //Method java/lang/Object.toString:()Ljava/lang/String;
11: invokevirtual #27; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
14: getstatic #17; //Field java/lang/System.out:Ljava/io/PrintStream;
17: aload_2
18: invokevirtual #33; //Method java/io/PrintStream.print:(Ljava/lang/Object;)V
21: return
}
Просто взглянув на основной метод, вы можете увидеть интересующие нас строки, где Code
равно 8 и 33.
В коде 8 показан байт-код для вызова o.toString()
. Здесь o
есть null
, и поэтому любая попытка вызова метода на null
приводит к NullPointerException
.
Код 18 показывает ваш объект null
, передаваемый как параметр методу PrintStream.print()
. Если посмотреть на исходный код этого метода, вы увидите, почему это не приводит к NPE:
public void print(Object obj) {
write(String.valueOf(obj));
}
и String.valueOf()
сделают это с помощью null
s:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Итак, вы можете видеть, что там есть тест, который имеет дело с null
и предотвращает NPE.