Почему нулевая ссылка печатается как “null”

В println здесь o.toString () выбрасывает NPE, но o1, нет. Зачем?

public class RefTest { public static void main(String[] args) { Object o = null; Object o1 = null; System.out.println(o.toString()); //throws NPE System.out.print(o1); // does not throw NPE } } 

Это может помочь показать вам байт-код. Взгляните на следующий выход javap вашего classа:

 > 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."":()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.

 System.out.println(o.toString()) 

o.toString() пытается разыменовать нулевой объект, чтобы преобразовать его в строку, прежде чем передать его в println .

 System.out.print(o1); 

Вызываемая print представляет собой вариант print(Object) , который сам проверяет, что объект не имеет значения null перед продолжением.

Это потому, что print(Object) использует String.valueOf(Object) для преобразования (в стороне: после преобразования println(Object) будет вести себя так, как если бы вызывается print(String) , print(Object) эффективно использует write(int) ). String.valueOf(Object) не выбрасывает NPE, как и o.toString() , и вместо этого определяется для возврата "null" для нулевого параметра.

  • Преобразование объекта Date в объект календаря
  • Обновление Eclipse не работает
  • NullPointerException в Java без StackTrace
  • Eclipse / Android: «Ошибки, выполняемые застройщиком Android Pre Compiler» по проекту ... »
  • getActionBar () возвращает Null (AppCompat-v7 21)
  • Атрибут checkbox seleniumа "checked"
  • Java-массив, NullPointerException?
  • Null pointer Exception - findViewById ()
  • Трассировка стека NullPointerException недоступна без агента отладки
  • android.app.Application не может быть создан из-за NullPointerException
  • Java 8 NullPointerException в Collectors.toMap
  • Давайте будем гением компьютера.