¿Cuál es la diferencia entre la variable de objeto no inicializada y la variable de objeto inicializada como nula en Java

12

Tengo las siguientes dos variables de objeto

Date a;
Date b=null;

Definitivamente tanto 'a' como 'b' no se refieren a ningún objeto.

Ahora si invoco la siguiente declaración

System.out.println(a.toString());

Habrá un error de tiempo de compilación, mientras que si invoco la siguiente declaración

System.out.println(b.toString());

No habrá error de tiempo de compilación pero habrá un error de tiempo de ejecución. ¿Cuál es la razón de esto y qué valor se almacenará realmente en 'b' para representar un valor nulo?

Harish_N
fuente
2
preguntó y respondió muchas veces en SO: ¿Por qué las variables locales no se inicializan en Java? , Variables no inicializadas y miembros en Java y en muchas preguntas vinculadas a estos
mosquito
@gnat, ¿alguna otra pregunta trata la diferencia entre "no inicializado" y "nulo"? El hecho de que la respuesta sea similar no significa que esta sea una pregunta duplicada.
DougM
@DougM seguro, ¿leíste la primera pregunta que me referí? "¿Hubo alguna razón por la cual los diseñadores de Java sintieron que las variables locales no deberían tener un valor predeterminado? En serio, si las variables de instancia pueden tener un valor predeterminado, ¿por qué no podemos hacer lo mismo con las variables locales?" (FWIW técnicamente no puede ser un duplicado, simplemente porque está en otro sitio)
mosquito
1
Eso no aborda la diferencia entre "no inicializado" e "inicializado como nulo", solo "¿por qué las variables no se inicializan automáticamente a nulo?" Mismo tema, pregunta ligeramente diferente.
DougM

Respuestas:

3

Eso es porque el estado de las variables locales está controlado dentro de su alcance

 // method/loop/if/try-catch etc...
 {
   Date d; // if it's not intialised in this scope then its not intialised  anywhere
 }

Que no es el caso para los campos

class Foo{
 Date d; // it could be intialised anywhere, so its out of control and java will set to null for you
}

Ahora, ¿por qué está bien establecer una variable en nula y usarla de inmediato? tal vez es un error histórico que a veces conduce a errores horribles

 {
  Date d = null;
  try{
  }catch{ // hide it here 
  }
  return d;
 } 

¿Cuál es la diferencia semántica?

Date d;

solo declara una variable que puede contener una referencia que apunta a un objeto de tipo Date, sin embargo

Date d= null; 

hace exactamente lo mismo, pero la referencia apunta a nulo esta vez, nulo es como cualquier referencia, ocupa un espacio de un puntero nativo, es decir, 4 bytes en máquinas de 32 bits y 8 bytes en máquinas de 64 bits

Sleiman Jneidi
fuente
esto parece simplemente repetir el punto hecho y explicado en una respuesta anterior publicada hace una hora
mosquito el
@gnat Gracias por tu comentario, pero no creo que sea así, saludos
Sleiman Jneidi
¿Quiere decir que nulo también es un objeto almacenado en algún lugar de la memoria y todas las variables de objeto asignadas con nulo apuntan a ese objeto nulo?
Harish_N
@ Harish.N no, no dije eso, dije que es una referencia y no un objeto
Sleiman Jneidi
En el ejemplo que ha dado 'd' es una referencia ... es una referencia a un objeto de tipo Fecha ... de manera similar si nulo es una referencia ... ¿a qué objeto se refiere ...?
Harish_N
19

No hay diferencia para los campos de clase. Son nullpor defecto para objetos, 0 para valores numéricos y falsepara booleanos.

Para variables declaradas en métodos, Java requiere que se inicialicen. No inicializarlos causa un error de tiempo de compilación cuando se accede a ellos.

¿Cual es la razón? Los campos de clase se pueden modificar por cualquier método. En cualquier orden se invoca el método. Todos los campos no privados pueden ser modificados por otras clases y / o clases que extiendan esa clase. Por lo tanto, no tiene sentido notificar acerca de una variable no inicializada, ya que puede asignarse en muchos, muchos lugares.

Sin embargo, las variables dentro de los métodos son locales y solo se pueden modificar dentro del método. Por lo tanto, es posible y racional señalar posibles errores. Y el compilador intenta hacerlo. Si sabe que el campo no está inicializado, mostrará un error, porque eso nunca es lo que desea. Si no está seguro, emitirá una advertencia para que pueda asegurarse.

public static class Test {
    Date a; // ok 
    Date b = null; // ok

    public void test() {
        Date c;
        Date d = null;

        System.out.println(a.toString());
        System.out.println(b.toString());
        System.out.println(c.toString()); // error
        System.out.println(d.toString()); // warning
    }
}
Dariusz
fuente