2011-09-10 19 views
11

En println, aquí o.toString() arroja NPE pero o1, no lo hace. ¿Por qué?¿Por qué la referencia nula se imprime como "nula"

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

Está [todo en la documentación] (http://download.oracle.com/javase/6/docs/api/java/io/PrintStream.html#print%28java.lang.Object%29). –

Respuesta

25

Podría ayudar mostrarle el bytecode. Echar un vistazo a la siguiente javap salida de su clase:

> 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 

} 

Con sólo mirar el método principal, se puede ver las líneas de interés son Code, donde es de 8 y 33.

Código 8 muestra el código de bytes para usted llamando al o.toString(). Aquí o es null y, por lo tanto, cualquier intento de invocación de un método en null da como resultado un NullPointerException.

El código 18 muestra que su objeto null se pasa como parámetro al método PrintStream.print(). Mirar el código fuente para este método le mostrará por qué esto hace no resultado en la NPE:

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

y String.valueOf() va a hacer esto con null s:

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

Así se puede ver que hay es una prueba que trata con null y previene un NPE.

+0

Excelente respuesta, gracias. – abc

+1

De nada. A menudo encuentro que mirar el resultado de 'javap' puede ser bastante perspicaz. Especialmente cuando uso cosas como AspectJ y otras tecnologías de tejer códigos, ¡solo para ver exactamente lo que han hecho con mi código! –

+0

sin necesidad de mirar el código. Todo está en la documentación. 'PrintStream :: println' dice que llama' String.valueOf', que establece explícitamente: "si el argumento es nulo, entonces una cadena igual a" null "; de lo contrario, se devuelve el valor de obj.toString()." – njzk2

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

o.toString() está tratando de eliminar la referencia de un objeto nulo para convertirlo en una cadena, antes de pasarla a println.

System.out.print(o1); 

El print ser llamado es la variante print(Object), que es en sí mismo la comprobación de que el objeto no es nulo antes de proceder.

Cuestiones relacionadas