Apa perbedaan antara variabel objek yang tidak diinisialisasi dan variabel objek yang diinisialisasi ke nol di Jawa

12

Saya memiliki dua variabel objek berikut

Date a;
Date b=null;

Jelas 'a' dan 'b' tidak mengacu pada objek apa pun.

Sekarang jika saya memohon pernyataan berikut

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

Akan ada kesalahan waktu kompilasi, sedangkan jika saya menjalankan pernyataan berikut

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

Tidak akan ada kesalahan waktu kompilasi tetapi akan ada kesalahan runtime. Apa alasannya dan nilai apa yang sebenarnya disimpan dalam 'b' untuk mewakili nilai nol?

Harish_N
sumber
2
ditanya dan dijawab berkali-kali di SO: Mengapa variabel lokal tidak diinisialisasi di Jawa? , Variabel dan anggota yang belum diinisialisasi di Jawa dan dalam banyak pertanyaan terkait dengan ini
nyamuk
@gnat, apakah ada pertanyaan lain yang membahas perbedaan antara "tidak diinisialisasi" dan "null"? Hanya karena jawabannya serupa bukan berarti ini adalah pertanyaan rangkap.
DougM
@DougM yakin, apakah Anda membaca pertanyaan pertama yang saya referensikan? "Apakah ada alasan mengapa perancang Jawa merasa bahwa variabel lokal tidak boleh diberi nilai default? Serius, jika variabel instan dapat diberi nilai default, lalu mengapa kita tidak bisa melakukan hal yang sama untuk variabel lokal?" (FWIW secara teknis tidak bisa menjadi duplikat, hanya karena ada di situs lain)
Agas
1
Itu tidak membahas perbedaan antara "tidak diinisialisasi" dan "diinisialisasi sebagai nol", hanya "mengapa variabel tidak secara otomatis diinisialisasi ke nol?" Topik yang sama, pertanyaan yang sedikit berbeda.
DougM

Jawaban:

3

Itu karena keadaan variabel lokal dikendalikan dalam ruang lingkupnya

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

Yang tidak berlaku untuk bidang

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

Sekarang, mengapa tidak masalah untuk mengatur variabel ke nol dan menggunakannya segera? mungkin itu adalah kesalahan historis yang terkadang mengarah pada kesalahan mengerikan

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

Sekarang apa perbedaan semantiknya?

Date d;

hanya mendeklarasikan variabel yang dapat menyimpan referensi yang menunjuk ke objek bertipe Date, namun

Date d= null; 

tidak persis sama tetapi referensi menunjuk ke nol kali ini, nol seperti referensi apa pun, dibutuhkan spasi dari penunjuk asli, yaitu 4 byte pada mesin 32-bit dan 8 byte pada mesin 64-bit

Sleiman Jneidi
sumber
ini sepertinya hanya mengulangi poin yang dibuat dan dijelaskan dalam jawaban sebelumnya yang diposting satu jam yang lalu
agas
@gnat Terima kasih atas komentar Anda, tapi saya rasa itu tidak, bersorak
Sleiman Jneidi
Maksud Anda null juga merupakan objek yang disimpan di suatu tempat dalam memori dan semua variabel objek yang ditugaskan dengan nol menunjuk ke objek nol itu.
Harish_N
@Harish.Tidak, saya tidak mengatakan itu, saya mengatakan itu referensi dan bukan objek
Sleiman Jneidi
Dalam contoh yang Anda berikan 'd' adalah referensi .. itu referensi ke objek bertipe Date ... sama halnya jika null adalah referensi .. ke objek apa yang dimaksud ..?
Harish_N
19

Tidak ada perbedaan untuk bidang kelas. Mereka secara nulldefault untuk objek, 0 untuk nilai numerik dan falseuntuk boolean.

Untuk variabel yang dideklarasikan dalam metode - Java mengharuskan mereka untuk diinisialisasi. Tidak menginisialisasi mereka menyebabkan kesalahan waktu kompilasi ketika mereka diakses.

Apa alasannya? Bidang kelas dapat dimodifikasi dengan metode apa pun. Dalam urutan apa pun metode ini dipanggil. Semua bidang non-pribadi dapat dimodifikasi oleh kelas lain dan / atau kelas yang memperluas kelas itu. Oleh karena itu, tidak ada gunanya memberitahukan tentang variabel yang tidak diinisialisasi, karena mungkin ditugaskan di banyak tempat.

Variabel di dalam metode, bagaimanapun, adalah lokal dan dapat dimodifikasi hanya di dalam metode itu sendiri. Karena itu adalah mungkin dan rasional untuk menunjukkan kemungkinan kesalahan. Dan kompiler mencoba melakukannya. Jika ia tahu bidang tidak diinisialisasi, itu akan menampilkan kesalahan, karena itu tidak pernah seperti yang Anda inginkan. Jika tidak yakin - itu akan memberi peringatan, sehingga Anda bisa memastikan.

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
sumber