为什么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()
的字节码。 这里o
是null
,所以任何在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参数。