简体   繁体   English

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

[英]Why does null reference print as “null”

In println, here o.toString() throws NPE but o1, does not. 在println中,这里o.toString()抛出NPE但是o1抛出NPE。 Why? 为什么?

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

It might help showing you the bytecode. 它可能有助于向您显示字节码。 Take a look at the following javap output of your class: 看一下你班级的以下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

}

Just looking at the main method, you can see the lines of interest are where Code is 8 and 33. 只需查看主要方法,您就可以看到感兴趣的行是Code为8和33的位置。

Code 8 shows the bytecode for you calling o.toString() . 代码8显示了调用o.toString()的字节码。 Here o is null and so any attempt on a method invocation on null results in a NullPointerException . 这里的onull ,因此对null的方法调用的任何尝试都会导致NullPointerException

Code 18 shows your null object being passed as a parameter to the PrintStream.print() method. 代码18显示了您的null对象作为参数传递给PrintStream.print()方法。 Looking at the source code for this method will show you why this does not result in the NPE: 看着这个方法会告诉你为什么,这并不在NPE导致的源代码:

public void print(Object obj) {
    write(String.valueOf(obj));
}

and String.valueOf() will do this with null s: String.valueOf()将使用null s执行此操作:

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

So you can see there is a test there which deals with null , and prevents an NPE. 所以你可以看到有一个测试处理null ,并阻止NPE。

It's because print(Object) uses String.valueOf(Object) for the conversion (aside: after the conversion println(Object) would behave as though print(String) was called, print(Object) effectively uses write(int) ). 这是因为print(Object)使用String.valueOf(Object)进行转换(除了:转换后println(Object)就像调用print(String)print(Object)有效地使用write(int) )。 String.valueOf(Object) doesn't throw the NPE like o.toString() does and is instead defined to return "null" for a null parameter. String.valueOf(Object)不像o.toString()那样抛出NPE,而是定义为null参数返回"null"

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

o.toString() is trying to dereference a null object to convert it to a string, before passing it to println . o.toString()尝试取消引用null对象以将其转换为字符串,然后再将其传递给println

System.out.print(o1);

The print being called is the print(Object) variant, which is itself checking that the object is not null before proceeding. print被称为是print(Object)的变体,这本身就是检查的对象不是继续之前空。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM