2011-12-21 28 views
9
public class JavaPuzzler { 

    public static void main(String[] args) { 
    JavaPuzzler javaPuzzler = null; 
    System.out.println(javaPuzzler.get()); 
    } 

    private static String get(){ 
     return "i am a java puzzler"; 
    } 
} 

Se podría pensar que debería tirar NullPointerException debido a que el principal método invoca método get() en variable local que se inicializa a null , y no se puede invocar un método en nulo.¿Cómo puedo llamar a un método en un objeto nulo?

Pero si ejecuta este programa, verá que imprime "soy un rompecabezas de Java".

¿Alguien puede darme la respuesta? Gracias de antemano.

+2

Creo que en su declaración de impresión su JavaPuzzler.get() con mayúscula J – Nik

+0

@Nikunj la pregunta es absolutamente correcta, no hay ningún error en la palabra. – Nik88

+0

Por favor, compruebe mi ans! – Nik

Respuesta

6

En el ejemplo de código, get() es un miembro estático que pertenece a la clase, no a una instancia. No necesita una instancia para invocar el método.

public static String get() // belongs globally to class, no instance required 
public String get() // belongs to instance 
+0

Esto parece un poco mal que llame a un método estático en una variable de instancia (aunque 'null'). Interesante, sin embargo. –

+1

@Andrew Marshall: si prueba el código en eclipse, se cambiará automáticamente a Class.call() desde instance.call() – Nik

1

Su método es el estático. Entonces solo podría ser llamado de una manera estática.

Por lo tanto, aunque lo está poniendo como javaPuzzler.get(), la llamada real será JavaPuzzler.get() y por lo tanto la impresión !!

3

El método get es estático, lo que significa que la referencia real en javaPuzzler se ignora en esa llamada, solo se utiliza el tipo de la variable.

1

Está llamando a un método estático, no necesita una instancia para llamarlo, por eso funciona.

1

Si intentamos llamar a un método utilizando el objeto NULL arrojará NullPointerException siempre que el método no sea estático.

Si el método es estático, se ejecutará.

Leer HERE para más referencia

4

Es porque el método es estático y, aunque se hace referencia a una instancia, la instancia no es necesario. La especificación del lenguaje Java explica por qué en section 8.4.3.2:

Un método que se declara estático se denomina método de clase. Un método de clase siempre se invoca sin referencia a un objeto particular.

Esto significa que no importa si javaPuzzler instancia es nula: el método "pertenece" a la clase, no a una instancia.

1

Como todo el mundo menciona aquí, funciona porque get() es un método estático. Aquí hay una manera en que puede pensar en esto:

Cuando define una clase en Java, lo que básicamente hace es definir los datos que contendrá un objeto y un conjunto de métodos que operan con esos datos. Ahora bien, aunque puede tener miles y miles de objetos, no tiene sentido tener copias de todos los métodos para cada uno de ellos. Lo que ocurre es que la clase almacena los métodos que defina y los ejecuta en el alcance del objeto que llama al método. Si intenta llamar a estos métodos en un objeto no inicializado, el objeto aún existe y el método todavía existe, pero no tiene validez para poder trabajar en el alcance, lo que le da el NullPointerException.

La excepción a esta regla son los métodos estáticos, que son métodos que no necesitan un ámbito: no se refieren a datos específicos del objeto. Es por eso que pueden ejecutarse independientemente de si el objeto está inicializado o no.

Solo recuerde que los objetos no tienen copias de sus métodos ... los métodos son simplemente llamados en el alcance de los datos del objeto. De modo que aún puede acceder a los métodos de objetos nulos (no inicializados), pero los métodos no estáticos no tienen datos para trabajar.

0

El compilador cambia automáticamente la llamada de instancia a una llamada de clase. Si usted tiene un decompilador se puede observar el cambio en el código de bytes generada:

... 
public static main([Ljava/lang/String;)V 
    L0 
    LINENUMBER 8 L0 
    ACONST_NULL 
    ASTORE 1 
    L1 
    LINENUMBER 9 L1 
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream; 
    INVOKESTATIC JavaPuzzler.get()Ljava/lang/String; 
    INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V 
    L2 
    LINENUMBER 11 L2 
    RETURN 
    L3 
    LOCALVARIABLE args [Ljava/lang/String; L0 L3 0 
    LOCALVARIABLE javaPuzzler LJavaPuzzler; L1 L3 1 
    MAXSTACK = 2 
    MAXLOCALS = 2 
... 
0

En el código anterior se ha dado función get() como estática. Las funciones estáticas y los miembros de datos no pertenecen a ningún objeto. Ellos pertenecen a la clase. Puede llamar a la función estática utilizando el objeto de clase, pero no es un buen enfoque, ya que consume memoria extra.

Dado que static, JavaPuzzler.get()); le dará la salida y no la excepción del puntero nulo.

Habría dado una excepción de puntero nulo en caso de que el método get() hubiera sido no estático.

Cuestiones relacionadas