Kata pengantar
Di Java, suatu objek harus diinisialisasi dengan benar sebelum dapat digunakan, yang ditentukan oleh spesifikasi Java. Baru -baru ini saya menemukan pertanyaan yang menarik, dan jawaban untuk pertanyaan ini menipu mata saya pada pandangan pertama. Lihatlah ketiga kategori ini:
paket com.ds.test; kelas publik atas {string Upperstring; Upper publik () {initializer.initialize (ini); }} Paket com.ds.test; kelas publik Lower Extends Upper {String Lowerstring = null; publik lebih rendah () {super (); System.out.println ("Atas:" + Upperstring); System.out.println ("Lower:" + Lowerstring); } public static void main (string final [] args) {new lower (); }} paket com.ds.test; public class initializer {static void initialize (akhir anupper atas) {if (anupper instanceof bawah) {lebih rendah lebih rendah = (lebih rendah) anupper; lower.lowerstring = "lowerInited"; } anupper.upperstring = "Upperinited"; }} Output apa yang dapat diperoleh dengan menjalankan kelas Lower ? Dalam contoh minimal ini, seluruh situasi dapat dilihat lebih mudah, tetapi situasi ini terjadi dalam kenyataan dan akan ada banyak kode yang mengganggu seseorang.
Bagaimanapun, outputnya seperti ini:
Atas: Upperinitedlower: null;
Meskipun tipe String digunakan dalam contoh kecil, kode aktual dari kelas Initializer memiliki objek delegasi untuk pendaftaran, yang sama dengan fungsi kelas Lower - setidaknya kelas Lower adalah niat. Tetapi untuk beberapa alasan itu tidak berhasil saat menjalankan aplikasi. Sebaliknya, jalur default digunakan dan objek delegasi tidak diatur (null).
Sekarang sedikit ubah kode Lower :
Paket com.ds.test; kelas publik Lower Extends Upper {String Lowerstring; publik lebih rendah () {super (); System.out.println ("Atas:" + Upperstring); System.out.println ("Lower:" + Lowerstring); } public static void main (string final [] args) {new lower (); }}Output sekarang terlihat seperti ini:
Atas: Upperinitedlower: Lowerinited
Pernahkah Anda menemukan perbedaan dalam kode?
Ya, bidang lowerString ini tidak lagi secara eksplisit diatur untuk mengosongkan. Mengapa ini membuatnya berbeda? Ngomong -ngomong, bukankah nilai default dari bidang jenis referensi (seperti String di sini) kosong? Tentu saja itu kosong. Ternyata bahwa sementara perubahan kecil ini jelas tidak mengubah perilaku kode dengan cara apa pun, itu membuat hasilnya berbeda.
Jadi, apa sebenarnya yang terjadi? Semuanya menjadi jelas saat memeriksa urutan inisialisasi:
1. Fungsi main() memanggil konstruktor Lower .
2. Sebuah contoh Lower sudah siap. Artinya semua bidang dibuat dan diisi dengan nilai default, misalnya, nilai default dari jenis referensi kosong dan nilai default dari tipe boolean false . Pada saat ini, tidak ada penugasan inline ke lapangan.
3. Konstruktor kelas induk dipanggil. Ini diberlakukan oleh karakteristik bahasa. Jadi sebelum hal lain terjadi, konstruktor atas dipanggil.
4. Konstruktor ini berjalan dan menentukan referensi ke contoh yang baru dibuat dari metode Initializer.initialize() .
5. Kelas Initializer menempelkan string baru ke dua bidang ( upperString dan lowerString ). Menetapkan nilai untuk kedua bidang tersebut dengan menggunakan instanceof yang sedikit kotor dari pemeriksaan instance bukanlah pola desain yang sangat baik, tetapi juga berhasil, jangan khawatir tentang itu. Setelah itu terjadi, referensi ke upperString dan lowerString tidak lagi kosong.
6. Panggilan untuk Initializer.initialize() selesai, dan konstruktor Upper juga selesai.
7. Sekarang semakin menarik: pembangunan contoh Lower berlanjut. Dengan asumsi bahwa penugasan =null tidak secara eksplisit ditentukan dalam deklarasi bidang lowerString , konstruktor Lower melanjutkan eksekusi dan mencetak dua string yang terhubung ke bidang.
Namun, jika ada operasi yang secara eksplisit menetapkan null, proses eksekusi akan sedikit berbeda: ketika konstruktor kelas induk selesai, inisialisasi variabel apa pun akan dilakukan sebelum sisa konstruktor berjalan (lihat Bagian 12.5 dari spesifikasi bahasa Java). Dalam hal ini, referensi string yang ditugaskan ke lowerString sebelumnya tidak ditugaskan lagi. Kemudian lanjutkan untuk menjalankan konstruksi fungsi yang tersisa, dan sekarang cetak nilai lowerString sebagai: NULL.
Ini adalah contoh yang bagus, tidak hanya untuk memfasilitasi perhatian kami pada beberapa detail tentang membuat objek (atau untuk mengetahui di mana harus memeriksa spesifikasi pengkodean Java, dicetak atau online), tetapi juga untuk menunjukkan mengapa menulis inisialisasi seperti ini buruk. Kita seharusnya tidak peduli dengan subkelas Atas sama sekali. Sebaliknya, jika karena alasan tertentu inisialisasi bidang tertentu tidak dapat dilakukan di subkelas itu sendiri, ia hanya akan memerlukan beberapa varian dari kelas pembantu inisialisasi sendiri. Dalam hal ini, jika Anda menggunakan String lowString atau String lowerString = null benar -benar tidak ada perbedaan, apa yang seharusnya.
Meringkaskan
Di atas adalah seluruh konten artikel ini. Saya berharap konten artikel ini akan membantu untuk belajar atau bekerja semua orang. Jika Anda memiliki pertanyaan, Anda dapat meninggalkan pesan untuk berkomunikasi.