Why does null reference print as "null"
It might help showing you the bytecode. Take a look at the following javap
output of your class:
> 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 shows the bytecode for you calling o.toString()
. Here o
is null
and so any attempt on a method invocation on null
results in a NullPointerException
.
Code 18 shows your null
object being passed as a parameter to the PrintStream.print()
method. Looking at the source code for this method will show you why this does not result in the NPE:
public void print(Object obj) {
write(String.valueOf(obj));
}
and String.valueOf()
will do this with 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.
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
.
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.