为什么null引用打印为“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输出:

 > 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()的字节码。 这里onull ,所以任何在null上的方法调用的尝试都会导致NullPointerException

代码18显示了您的null对象作为PrintStream.print()方法的parameter passing。 看这个方法的源代码会告诉你为什么这不会导致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(); } 

所以你可以看到有一个testing,它处理null ,并防止NPE。

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

o.toString()试图在将对象传递给println之前解引用空对象以将其转换为string。

 System.out.print(o1); 

被调用的print(Object)print(Object)变体,在继续之前它本身检查对象是否为空。

这是因为print(Object)使用String.valueOf(Object)进行转换(另一方面:在转换println(Object)之后, print(String)被调用, print(Object)有效地使用write(int) )。 String.valueOf(Object)不像o.toString()那样抛出NPE,而是定义为返回"null"作为null参数。