Saya mengamati bahwa kelas-kelas luar dapat mengakses variabel-variabel instance kelas privat. Bagaimana ini mungkin? Berikut adalah contoh kode yang menunjukkan hal yang sama:
class ABC{
class XYZ{
private int x=10;
}
public static void main(String... args){
ABC.XYZ xx = new ABC().new XYZ();
System.out.println("Hello :: "+xx.x); ///Why is this allowed??
}
}
Mengapa perilaku ini diizinkan?
new ABC().new XYZ()
Jawaban:
Kelas dalam hanyalah cara untuk memisahkan beberapa fungsi yang benar-benar milik kelas luar asli. Mereka dimaksudkan untuk digunakan ketika Anda memiliki 2 persyaratan:
Dengan persyaratan ini, kelas dalam memiliki akses penuh ke kelas luarnya. Karena mereka pada dasarnya adalah anggota dari kelas luar, masuk akal bahwa mereka memiliki akses ke metode dan atribut dari kelas luar - termasuk privat.
sumber
Jika Anda ingin menyembunyikan anggota pribadi dari kelas batin Anda, Anda dapat mendefinisikan Antarmuka dengan anggota publik dan membuat kelas dalam anonim yang mengimplementasikan antarmuka ini. Contoh di bawah:
sumber
x
publik di sini, itu tidak diizinkanmMember.x
.Kelas dalam (untuk tujuan kontrol akses) dianggap sebagai bagian dari kelas yang mengandung. Ini berarti akses penuh ke semua privat.
Cara ini diimplementasikan menggunakan metode yang dilindungi paket sintetik: Kelas dalam akan dikompilasi ke kelas yang terpisah dalam paket yang sama (ABC $ XYZ). JVM tidak mendukung level isolasi ini secara langsung, sehingga pada level bytecode ABC $ XYZ akan memiliki metode yang dilindungi paket yang digunakan kelas luar untuk sampai ke metode / bidang pribadi.
sumber
Ada jawaban yang benar muncul pada pertanyaan lain yang mirip dengan ini: Mengapa anggota pribadi dari kelas bersarang dapat diakses dengan metode kelas melampirkan?
Dikatakan ada definisi pelingkupan pribadi pada JLS - Menentukan Aksesibilitas :
sumber
Kasus penggunaan penting IMHO untuk kelas dalam adalah pola pabrik. Kelas terlampir dapat menyiapkan turunan dari kelas dalam tanpa batasan akses dan meneruskan turunan ke dunia luar, di mana akses pribadi akan dihormati.
Bertentangan dengan abyx yang mendeklarasikan class static tidak mengubah batasan akses ke kelas yang menyertakan, seperti yang ditunjukkan di bawah ini. Juga pembatasan akses antara kelas statis di kelas tertutup yang sama berfungsi. Saya terkejut ...
sumber
Pembatasan akses dilakukan berdasarkan per kelas. Tidak ada cara untuk metode yang dinyatakan dalam kelas untuk tidak dapat mengakses semua anggota instance / kelas. Ini masuk akal bahwa kelas-kelas dalam juga memiliki akses tanpa batas ke anggota kelas luar, dan kelas luar memiliki akses tanpa batas ke anggota kelas dalam.
Dengan menempatkan kelas di dalam kelas lain, Anda membuatnya terikat erat dengan implementasi, dan apa pun yang merupakan bagian dari implementasi harus memiliki akses ke bagian lain.
sumber
Logika di balik kelas batin adalah bahwa jika Anda membuat kelas dalam di kelas luar, itu karena mereka perlu berbagi beberapa hal, dan dengan demikian masuk akal bagi mereka untuk dapat memiliki lebih banyak fleksibilitas daripada kelas "biasa".
Jika, dalam kasus Anda, tidak masuk akal bagi kelas untuk dapat melihat cara kerja masing-masing - yang pada dasarnya berarti bahwa kelas batin hanya dapat dibuat sebagai kelas reguler, Anda dapat mendeklarasikan kelas dalam sebagai
static class XYZ
. Menggunakanstatic
akan berarti mereka tidak akan berbagi status (dan, misalnyanew ABC().new XYZ()
tidak akan berfungsi, dan Anda harus menggunakannyanew ABC.XYZ()
.Tetapi, jika itu masalahnya, Anda harus memikirkan apakah
XYZ
benar-benar harus menjadi kelas dalam dan bahwa mungkin itu pantas sendiri) Terkadang masuk akal untuk membuat kelas dalam statis (misalnya, jika Anda membutuhkan kelas kecil yang mengimplementasikan antarmuka yang digunakan oleh kelas luar Anda, dan itu tidak akan membantu di tempat lain). Tetapi sekitar setengah dari waktu seharusnya dibuat kelas luar.sumber
Thilo menambahkan jawaban yang bagus untuk pertanyaan pertama Anda, "Bagaimana ini mungkin?" Saya ingin menguraikan sedikit pada pertanyaan kedua: Mengapa perilaku ini diizinkan?
Sebagai permulaan, mari kita menjadi sangat jelas bahwa perilaku ini tidak terbatas pada kelas dalam, yang menurut definisi adalah tipe bersarang non-statis. Perilaku ini diperbolehkan untuk semua tipe bersarang, termasuk enum bersarang dan antarmuka yang harus statis dan tidak dapat memiliki instance terlampir. Pada dasarnya, model ini adalah penyederhanaan ke pernyataan berikut: Kode bersarang memiliki akses penuh ke kode terlampir - dan sebaliknya.
Jadi mengapa? Saya pikir contoh menggambarkan hal itu dengan lebih baik.
Pikirkan tubuh dan otak Anda. Jika Anda menyuntikkan heroin ke lengan Anda, otak Anda menjadi tinggi. Jika wilayah amygdala otak Anda melihat apa yang dia yakini sebagai ancaman terhadap keselamatan pribadi Anda, katakanlah tawon misalnya, ia akan membuat tubuh Anda berbalik dan berlari ke bukit tanpa Anda "berpikir" dua kali tentang hal itu.
Jadi, otak adalah bagian intrinsik dari tubuh - dan anehnya, sebaliknya. Menggunakan kontrol akses antara entitas yang terkait erat seperti kehilangan klaim hubungan mereka. Jika Anda benar-benar membutuhkan kontrol akses, maka Anda perlu memisahkan kelas lebih banyak menjadi unit yang benar-benar berbeda. Sampai saat itu, mereka adalah unit yang sama. Contoh pendorong untuk studi lebih lanjut adalah dengan melihat bagaimana Java
Iterator
biasanya diimplementasikan.Akses tanpa batas dari kode penutup ke kode bersarang membuatnya, sebagian besar, agak tidak berguna untuk menambahkan pengubah akses ke bidang dan metode dari tipe bersarang. Melakukan hal itu menambah kekacauan dan mungkin memberikan rasa aman yang salah untuk pendatang baru bahasa pemrograman Java.
sumber
Kelas dalam dianggap sebagai atribut dari kelas luar. Oleh karena itu, tidak peduli variabel instance kelas dalam adalah pribadi atau tidak, kelas luar dapat mengakses tanpa masalah sama seperti mengakses atribut pribadi lainnya (variabel).
sumber
Karena
main()
metode Anda ada diABC
kelas, yang dapat mengakses kelas batinnya sendiri.sumber
ABC
kelas dapat mengakses kelas yang bersarang diABC
kelas, tetapi mengapa mereka dapat mengakses anggota kelas pribadi yang bersarang diABC
kelas di Jawa.