2012-04-10 29 views
16
public class Main 
{ 
    public static void main(String []ar) 
    { 
     A m = new A(); 
     System.out.println(m.getNull().getValue()); 
    } 
} 

class A 
{ 
    A getNull() 
    { 
     return null; 
    } 

    static int getValue() 
    { 
     return 1; 
    } 
} 

Me encontré con esta pregunta en un libro de SCJP. El código imprime 1 en lugar de un NPE como sería de esperar. ¿Podría alguien explicar la razón por la cual?¿Por qué este código NO devuelve NullPointerException?

Respuesta

18

se comporta como debe según la Java Language Specification:

una referencia nula se puede usar para acceder a una variable de clase (estática) sin causar una excepción.

22

Básicamente está llamando a un método estático como si fuera un método de instancia. Eso sólo se resuelve con una llamada al método estático, por lo que es como si hubieras escrito:

A m = new A(); 
m.getNull(); 
System.out.println(A.getValue()); 

OMI el hecho de que su código es legal en absoluto es un defecto de diseño en Java. Se le permite escribir código muy engañoso, con Thread.sleep como un ejemplo que siempre uso:

Thread thread = new Thread(someRunnable); 
thread.start(); 
thread.sleep(1000); 

Qué hilo transmite esto a dormir? El actual, "por supuesto" ...

6

Las llamadas al método estático se resuelven en tiempo de compilación. El compilador ve que getNull() tiene un valor de retorno de tipo A que tiene un método getValue() estático (y ningún método de instancia del mismo nombre), por lo que en el bytecode se ignora el valor de retorno real de getNull() y se invoca A.getValue().

1

getNull function devuelve un objeto A. getValue se declara como estático, y solo necesita el nombre de la clase para funcionar, como en A.getValue(). Como getNull devuelve (de hecho) un objeto A ... obtendrá 1

1

System.out.println (m.getNull(). GetValue()); esta línea de código es la misma que System.out.println (A.getValue());

como porque el método getValue() es estática y y todo llamada estática iniciado en tiempo de compilación en java. por lo que no produce ningún error una vez que realice getValue() en no estático esto producirá un error porque se ejecutará en tiempo de ejecución

+1

Esto es incorrecto, 'm.getNull()' ** does ** ser llamado. Ver la respuesta de Jon. – assylias

+0

m.getNull() se invocará solo si getNull no es estático. que mencioné antes. –

+1

Lo que quise decir es que 'System.out.println (m.getNull(). GetValue());' no es equivalente a 'System.out.println (A.getValue());'. Es equivalente a 'm.getNull(); System.out.println (A.getValue()); '. – assylias

Cuestiones relacionadas