2011-09-10 3 views
11

In println, qui o.toString() genera NPE ma o1, no. Perché?Perché il riferimento null viene stampato come "null"

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

È [tutto nella documentazione] (http://download.oracle.com/javase/6/docs/api/java/io/PrintStream.html#print%28java.lang.Object%29). –

risposta

25

Potrebbe essere utile mostrarti il ​​bytecode. Date un'occhiata al javap uscita della classe che segue:

> 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 

} 

Solo guardando il metodo principale, è possibile vedere le linee di interesse sono dove Code è 8 e 33.

Codice 8 mostra il bytecode per te chiamando o.toString(). Qui o è null e quindi qualsiasi tentativo di invocazione di un metodo su null produce un NullPointerException.

Il codice 18 mostra l'oggetto null passato come parametro al metodo PrintStream.print(). Guardando il codice sorgente di questo metodo vi mostrerà il motivo per cui questo non non risultato nella NPE:

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

e String.valueOf() faremo con null s:

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

Così si può vedere lì è un test lì che si occupa di null e impedisce un NPE.

+0

Ottima risposta, grazie. – abc

+1

Prego. Trovo spesso che guardare l'output di 'javap' può essere abbastanza perspicace. Soprattutto quando si usano cose come AspectJ e altre tecnologie di tessitura del codice - solo per vedere esattamente quello che hanno fatto al mio codice! –

+0

non c'è bisogno di guardare il codice. È tutto nella documentazione. 'PrintStream :: println' dice che chiama' String.valueOf', che afferma esplicitamente: "se l'argomento è nullo, allora una stringa uguale a" null ", altrimenti viene restituito il valore di obj.toString()." – njzk2

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

o.toString() sta cercando di dereference un oggetto nullo per convertirlo in una stringa, prima di passare a println.

System.out.print(o1); 

Il print chiamato è la variante print(Object), a sua volta controllato che l'oggetto non è nullo prima di procedere.