Saat kelas dalam ditambahkan ke Java dalam versi 1.1 bahasa, kelas tersebut awalnya didefinisikan sebagai transformasi ke kode 1.0 yang kompatibel. Jika Anda melihat contoh transformasi ini, saya pikir itu akan membuatnya jauh lebih jelas bagaimana sebenarnya kelas dalam bekerja.
Perhatikan kode dari jawaban Ian Roberts:
public class Foo {
int val;
public Foo(int v) { val = v; }
class Bar {
public void printVal() {
System.out.println(val);
}
}
public Bar createBar() {
return new Bar();
}
}
Ketika diubah menjadi kode yang kompatibel 1.0, kelas dalam itu Barakan menjadi seperti ini:
class Foo$Bar {
private Foo this$0;
Foo$Bar(Foo outerThis) {
this.this$0 = outerThis;
}
public void printVal() {
System.out.println(this$0.val);
}
}
Nama kelas dalam diawali dengan nama kelas luar untuk membuatnya unik. this$0Anggota pribadi tersembunyi ditambahkan yang memegang salinan luar this. Dan konstruktor tersembunyi dibuat untuk menginisialisasi anggota itu.
Dan jika Anda melihat createBarmetodenya, itu akan berubah menjadi seperti ini:
public Foo$Bar createBar() {
return new Foo$Bar(this);
}
Jadi mari kita lihat apa yang terjadi ketika Anda menjalankan kode berikut.
Foo f = new Foo(5);
Foo.Bar b = f.createBar();
b.printVal();
Pertama kita membuat instance dari Foodan menginisialisasi valanggota ke 5 (yaitu f.val = 5).
Selanjutnya kita panggil f.createBar(), yang membuat instance dari Foo$Bardan menginisialisasi this$0anggota ke nilai yang thisditeruskan dari createBar(yaitu b.this$0 = f).
Akhirnya kita sebut b.printVal()yang mencoba mencetak b.this$0.valyaitu f.valyang 5.
Nah, itu adalah contoh reguler dari kelas dalam. Mari kita lihat apa yang terjadi saat membuat contoh Bardari luar Foo.
Foo f = new Foo(5);
Foo.Bar b = f.new Bar();
b.printVal();
Menerapkan transformasi 1.0 kami lagi, baris kedua itu akan menjadi seperti ini:
Foo$Bar b = new Foo$Bar(f);
Ini hampir identik dengan f.createBar()panggilan. Sekali lagi kami membuat instance dari Foo$Bardan menginisialisasi this$0anggota ke f. Sekali lagi b.this$0 = f,.
Dan lagi ketika Anda menelepon b.printVal(), Anda mencetak b.thi$0.valyang f.valmana 5.
Hal utama yang perlu diingat adalah bahwa kelas dalam memiliki anggota tersembunyi yang memegang salinan dari thiskelas luar. Saat Anda membuat instance kelas dalam dari dalam kelas luar, itu secara implisit diinisialisasi dengan nilai saat ini this. Saat Anda membuat instance kelas dalam dari luar kelas luar, Anda secara eksplisit menentukan instance kelas luar mana yang akan digunakan, melalui awalan pada newkata kunci.