在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
}
}
答案 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()
的字节码。此处o
为null
,因此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);
被调用的print
是print(Object)
变体,它本身在继续之前检查对象是否为空。