Qual é a diferença entre a variável de objeto não inicializada e a variável de objeto inicializada como nula em Java

12

Eu tenho as seguintes duas variáveis ​​de objeto

Date a;
Date b=null;

Definitivamente, 'a' e 'b' não estão se referindo a nenhum objeto.

Agora, se eu chamar a seguinte declaração

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

Haverá um erro de tempo de compilação, enquanto que se eu chamar a seguinte instrução

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

Não haverá erro de tempo de compilação, mas haverá um erro de tempo de execução. Qual é o motivo disso e qual valor será realmente armazenado em 'b' para representar um valor nulo?

Harish_N
fonte
2
perguntou e respondeu várias vezes no SO: Por que as variáveis ​​locais não são inicializadas em Java? , Variáveis não inicializadas e membros em Java e em muitas questões ligadas a estes
mosquito
@gnat, alguma outra pergunta lida com a diferença entre "não inicializado" e "nulo"? Só porque a resposta é semelhante, não significa que esta seja uma pergunta duplicada.
DougM
@ DougM claro, você leu a primeira pergunta que me referi? "Havia alguma razão para os designers de Java acharem que variáveis ​​locais não deveriam receber um valor padrão? Sério, se variáveis ​​de instância podem receber um valor padrão, por que não podemos fazer o mesmo com variáveis ​​locais?" (FWIW não pode tecnicamente ser um duplicado, simplesmente porque é em outro local)
mosquito
1
Isso não aborda a diferença entre "não inicializado" e "inicializado como nulo", apenas "por que as variáveis ​​não são automaticamente inicializadas como nulas?" Mesmo tópico, pergunta um pouco diferente.
DougM

Respostas:

3

Isso ocorre porque o estado das variáveis ​​locais é controlado dentro de seu escopo

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

O que não é o caso dos campos

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

Agora, por que é bom definir uma variável como nula e usá-la imediatamente? talvez esse seja um erro histórico que às vezes leva a erros horríveis

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

Agora, qual é a diferença semântica?

Date d;

apenas declara a variável que pode conter uma referência que aponta para um objeto do tipo Date, no entanto

Date d= null; 

faz exatamente o mesmo, mas a referência está apontando para null desta vez, null é como qualquer referência, ocupa um espaço de um ponteiro nativo, que é de 4 bytes em máquinas de 32 bits e 8 bytes em máquinas de 64 bits

Sleiman Jneidi
fonte
este parece meramente ponto repeat feito e explicado em uma resposta antes postou uma hora atrás
mosquito
Graças @gnat para o seu comentário, mas eu não acho que isso é, aplausos
Sleiman Jneidi
Você quer dizer que null também é um objeto armazenado em algum lugar na memória e todas as variáveis ​​de objeto atribuídas com null estão apontando para esse objeto nulo.
Harish_N
@ Harish.N não, eu não disse isso, eu disse a sua referência e não um objeto
Sleiman Jneidi
No exemplo que você forneceu, 'd' é uma referência .. é uma referência a um objeto do tipo Data ... da mesma forma se null for uma referência .. a qual objeto ele se refere ..?
Harish_N
19

Não há diferença para os campos de classe. Eles são nullpor padrão para objetos, 0 para valores numéricos e falsepara booleanos.

Para variáveis ​​declaradas nos métodos - Java requer que elas sejam inicializadas. Não inicializá-los causa um erro de tempo de compilação quando são acessados.

Qual o motivo? Os campos de classe podem ser modificados por qualquer método. Em qualquer ordem, o método é chamado. Todos os campos não privados podem ser modificados por outras classes e / ou classes que estendem essa classe. Portanto, não faz sentido notificar sobre uma variável não inicializada, pois ela pode ser atribuída em muitos, muitos lugares.

Variáveis ​​dentro de métodos, no entanto, são locais e podem ser modificadas apenas dentro do próprio método. Portanto, é possível e racional apontar possíveis erros. E o compilador tenta fazer isso. Se souber que o campo não foi inicializado, ele mostrará um erro, porque nunca é isso que você deseja. Se não tiver certeza - será emitido um aviso para que você possa ter certeza.

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
fonte