为什么 System.out.println() 不抛出 NullPointerException?

Why doesn't System.out.println() throw NullPointerException?

这可能是一个非常基本的问题,但我仍然不知道答案。

String abc = null;    
System.out.println(abc);

为什么System.out.println打印"null"而不抛出NullPointerException

你可以看看PrintStream源代码:

public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

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

如您所见,null 案例仅通过打印 "null".

来处理

因为它最终到达 print 方法,该方法打印 "null" for a null String :

public void println(String x) {
    synchronized (lock) {
        print(x);
        println();
    }
}

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

任何空引用的打印都存在相同的行为(在这种情况下,"null" 字符串由 String.valueOf(null) 返回:

public void println(Object x) {
    String s = String.valueOf(x);
    synchronized (lock) {
        print(s);
        println();
    }
}

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

null 在 print 函数中是特殊的:

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

它的行为与记录的一样。 PrintStream.println(String) 记录为:

Prints a String and then terminate the line. This method behaves as though it invokes print(String) and then println().

PrintStream.print(String) 记录为:

Prints a string. If the argument is null then the string "null" is printed. Otherwise, the string's characters are converted into bytes according to the platform's default character encoding, and these bytes are written in exactly the manner of the write(int) method.

如有疑问,请阅读文档:)

根据PrintStream#println()

Prints an Object and then terminate the line. This method calls at first String.valueOf(x) to get the printed object's string value, then behaves as though it invokes print(String) and then println().

根据String#valueOf

Returns the string representation of the Object argument. If the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.

System.out.print函数源代码。如果打印字符串为空,则设置为 "null"

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

嗯,在某些情况下,System.out.println 可能会抛出一个 NullPointerException 让你认为这就是它的工作原理。

如果您有一个复杂的对象并在其中创建了自己的 toString() 方法,则该方法中可能会发生错误。您可能无意或有意地编写代码,使 NPE 确实发生。对象本身不为空,但其中的某些属性可能为空。

这种编码很可能是不鼓励的,因为它确实违反了合同,正如其他人所指出的那样。所需的行为是将空对象表示为 null 而不是抛出 NPE。