Jaka jest różnica między niezainicjowaną zmienną obiektową a zmienną obiektową zainicjowaną na wartość NULL w Javie

12

Mam następujące dwie zmienne obiektowe

Date a;
Date b=null;

Zdecydowanie zarówno „a”, jak i „b” nie odnoszą się do żadnych obiektów.

Teraz, jeśli przywołam następujące oświadczenie

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

Wystąpi błąd czasu kompilacji, natomiast jeśli wywołam następującą instrukcję

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

Nie wystąpi błąd czasu kompilacji, ale wystąpi błąd czasu wykonywania. Jaki jest tego powód i jaka wartość będzie faktycznie przechowywana w „b” w celu reprezentowania wartości zerowej?

Harish_N
źródło
2
wielokrotnie zadawali i odpowiadali w SO: Dlaczego zmienne lokalne nie są inicjowane w Javie? , Niezainicjowane zmienne i elementy w Javie oraz w wielu powiązanych z nimi pytaniach
gnat
@gnat, czy jakieś inne pytania dotyczą różnicy między „niezainicjowanym” a „zerowym”? To, że odpowiedź jest podobna, nie oznacza, że ​​jest to duplikat pytania.
DougM
@DougM, czy przeczytałeś pierwsze pytanie, które zadałem? „Czy był jakiś powód, dla którego projektanci Javy uważali, że zmienne lokalne nie powinny mieć wartości domyślnej? Poważnie, jeśli zmienne instancji mogą otrzymać wartość domyślną, to dlaczego nie możemy zrobić tego samego dla zmiennych lokalnych?” (FWIW to technicznie nie może być duplikatem, po prostu dlatego, że znajduje się na innej stronie)
gnat
1
To nie rozwiązuje różnicy między „niezainicjalizowanym” a „zainicjowanym jako null”, a jedynie „dlaczego zmienne nie są automatycznie inicjowane do null?” Ten sam temat, nieco inne pytanie.
DougM

Odpowiedzi:

3

Dzieje się tak, ponieważ stan zmiennych lokalnych jest kontrolowany w jego zakresie

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

Nie dotyczy to pól

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

Dlaczego warto ustawić zmienną na null i użyć jej natychmiast? może to historyczny błąd, który czasami prowadzi do strasznych błędów

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

Jaka jest różnica semantyczna?

Date d;

po prostu deklaruje zmienną, która może pomieścić odsyłającego wynika, że punkty do obiektu typu Date, jednak

Date d= null; 

robi dokładnie to samo, ale tym razem odwołanie wskazuje null, null jest jak każde odwołanie, zajmuje miejsce natywnego wskaźnika, czyli 4 bajty na komputerach 32-bitowych i 8 bajtów na komputerach 64-bitowych

Sleiman Jneidi
źródło
wydaje się to jedynie powtórzyć punkt poczyniony i wyjaśniony we wcześniejszej odpowiedzi opublikowanej godzinę temu
komara
@gnat Dziękuję za komentarz, ale nie sądzę, że tak, na zdrowie
Sleiman Jneidi
Czy masz na myśli, że null jest także obiektem przechowywanym gdzieś w pamięci, a wszystkie zmienne obiektu przypisane null wskazują na ten obiekt null.
Harish_N
@ Harish.N nie, nie powiedziałem tego, powiedziałem, że jest to odniesienie, a nie przedmiot
Sleiman Jneidi
W podanym przykładzie „d” jest odwołaniem .. jest odwołaniem do obiektu typu Date… podobnie, jeśli null jest odwołaniem… do jakiego obiektu odnosi się…?
Harish_N
19

Nie ma różnicy dla pól klas. Są nulldomyślnie dla obiektów, 0 dla wartości liczbowych i falseboolean.

W przypadku zmiennych zadeklarowanych w metodach - Java wymaga ich inicjalizacji. Nie zainicjowanie ich powoduje błąd czasu kompilacji, gdy są dostępne.

Jaki jest powód? Pola klasy można modyfikować dowolną metodą. W dowolnej kolejności wywoływana jest metoda. Wszystkie nieprywatne pola mogą być modyfikowane przez inne klasy i / lub klasy rozszerzające tę klasę. Dlatego nie ma sensu powiadamiać o niezainicjowanej zmiennej, ponieważ można ją przypisać w wielu, wielu miejscach.

Zmienne w metodach są jednak lokalne i można je modyfikować tylko w samej metodzie. Dlatego wskazanie możliwych błędów jest zarówno możliwe, jak i racjonalne. I kompilator próbuje to zrobić. Jeśli wie, że pole nie zostało zainicjowane, wyświetli błąd, ponieważ nigdy tego nie chcesz. Jeśli nie jest to pewne - wyświetli ostrzeżenie, abyś mógł się upewnić.

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
źródło