为什么null引用打印为“null”

时间:2011-09-10 20:13:20

标签: java nullpointerexception

在println中,这里o.toString()抛出NPE但是o1抛出NPE。为什么呢?

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
    }
}

3 个答案:

答案 0 :(得分:27)

它可能有助于向您显示字节码。请查看您班级的以下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()方法。查看此方法的源代码将显示为什么在NPE中 not 结果为止

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。

答案 1 :(得分:5)

这是因为print(Object)使用String.valueOf(Object)进行转化(除了:转化后println(Object)表现得像调用print(String)一样,print(Object)有效地使用{ {1}})。 write(int)不像String.valueOf(Object)那样抛出NPE,而是定义为返回o.toString()的空参数。

答案 2 :(得分:5)

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

o.toString()尝试取消引用null对象,将其转换为字符串,然后再将其传递给println

System.out.print(o1);

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