Почему toString() в экземпляре объекта (который является нулевым) не бросает NPE?

Рассмотрим ниже:

Object nothingToHold = null;

System.out.println(nothingToHold);  //  Safely prints 'null'

Здесь Sysout должен ожидать String. Поэтому toString() должен быть вызван на экземпляр.

Итак, почему null.toString() работает потрясающе? Sysout заботится об этом?

EDIT: На самом деле я увидел эту странную вещь с append() StringBuilder. Так что попробовал с Sysout. Оба ведут себя одинаково. Так и этот метод заботится?

Ответ 1

PrintWriter println(Object) (это метод, вызываемый при записи System.out.println(nothingToHold)), вызывает String.valueOf(x), как описано в Javadoc:

/**
 * Prints an Object and then terminates the line.  This method calls
 * at first String.valueOf(x) to get the printed object string value,
 * then behaves as
 * though it invokes <code>{@link #print(String)}</code> and then
 * <code>{@link #println()}</code>.
 *
 * @param x  The <code>Object</code> to be printed.
 */
public void println(Object x)

String.valueOf(Object) преобразует значение null в значение "null":

/**
 * Returns the string representation of the <code>Object</code> argument.
 *
 * @param   obj   an <code>Object</code>.
 * @return  if the argument is <code>null</code>, then a string equal to
 *          <code>"null"</code>; otherwise, the value of
 *          <code>obj.toString()</code> is returned.
 * @see     java.lang.Object#toString()
 */
public static String valueOf(Object obj)

Ответ 2

Метод PrintStream#println(Object s) вызывает PrintStream#print(String s), который сначала проверяет, является ли аргумент null, и если он есть, то просто устанавливает "null" для печати как простой String.

Однако то, что передается методу .print(), равно "null" как String, потому что String.valueOf(String s) возвращает "null" перед вызовом метода .print().

public void print(String s) {
    if (s == null) {
        s = "null";
    }
    write(s);
}

Ответ 3

Вот документация для println()

Распечатывает строку, за которой следует новая строка. Строка преобразуется в массив байтов с использованием кодировки, выбранной при построении этот поток. Затем байты записываются в целевой поток с помощью писать (INT).

Если возникает ошибка ввода-вывода, в этом состоянии ошибки потока установлено значение true.

NULL может преобразовывать в байты.

Ответ 4

    Object nothingToHold = null;
   System.out.println(nothingToHold != null ? nothingToHold : "null String or any thing else");

Это будет отображать вывод, если NothingToHold (Object) не равно null, иначе оно печатает сообщение как "null String или что-то еще"

Ответ 5

Код говорит громче, чем слова.

class PrintStream {
    public void println(Object x) {
        String s = String.valueOf(x);
        // ...
    }
}

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