class OuterClass {
...
static class StaticNestedClass {
...
}
class InnerClass {
...
}
}
Kelas dalaman ini dipanggil bersarang. Mereka dibahagikan kepada 2 jenis:
- Kelas bersarang bukan statik. Ini juga dipanggil kelas dalaman.
- Kelas bersarang statik.
- kelas tempatan
- kelas tanpa nama

public class Bicycle {
private String model;
private int weight;
public Bicycle(String model, int weight) {
this.model = model;
this.weight = weight;
}
public void start() {
System.out.println("Let's go!");
}
public class Handlebar {
public void right() {
System.out.println("Steer right!");
}
public void left() {
System.out.println("Steer left!");
}
}
public class Seat {
public void up() {
System.out.println("Seat up!");
}
public void down() {
System.out.println("Seat down!");
}
}
}
Di sini kita mempunyai Bicycle
kelas. Ia mempunyai 2 medan dan 1 kaedah: start()
. 
Handlebar
dan Seat
. Kod mereka ditulis di dalam Bicycle
kelas. Ini adalah kelas lengkap: seperti yang anda lihat, setiap daripada mereka mempunyai kaedah sendiri. Pada ketika ini, anda mungkin mempunyai soalan: mengapa di dunia ini kita akan meletakkan satu kelas di dalam kelas lain? Mengapa menjadikan mereka kelas dalaman? Baiklah, katakan kita memerlukan kelas berasingan untuk konsep hendal dan tempat duduk dalam program kita. Sudah tentu, kita tidak perlu membuat mereka bersarang! Kita boleh buat kelas biasa. Sebagai contoh, seperti ini:
public class Handlebar {
public void right() {
System.out.println("Steer right!");
}
public void left() {
System.out.println("Steer left");
}
}
public class Seat {
public void up() {
System.out.println("Seat up!");
}
public void down() {
System.out.println("Seat down!");
}
}
Soalan yang sangat bagus! Sudah tentu, kita tidak terhad oleh teknologi. Melakukannya sudah tentu satu pilihan. Di sini, perkara penting ialah reka bentuk kelas yang betul dari perspektif program tertentu dan tujuannya. Kelas dalaman adalah untuk mengasingkan entiti yang berkait rapat dengan entiti lain. Bar hendal, tempat duduk dan pedal adalah komponen basikal. Dipisahkan dari basikal, mereka tidak masuk akal. Jika kami membuat semua konsep ini memisahkan kelas awam, kami akan mempunyai kod seperti ini dalam program kami:
public class Main {
public static void main(String[] args) {
Handlebar handlebar = new Handlebar();
handlebar.right();
}
}
Hmm... Maksud kod ni pun susah nak terangkan. Kami mempunyai beberapa hendal yang samar-samar (Mengapa perlu? Tidak ada idea, sejujurnya). Dan pemegang ini membelok ke kanan... dengan sendirinya, tanpa basikal... atas sebab tertentu. Dengan mengasingkan konsep hendal daripada konsep basikal, kami kehilangan sedikit logik dalam program kami. Menggunakan kelas dalaman, kod itu kelihatan sangat berbeza:
public class Main {
public static void main(String[] args) {
Bicycle peugeot = new Bicycle("Peugeot", 120);
Bicycle.Handlebar handlebar = peugeot.new Handlebar();
Bicycle.Seat seat = peugeot.new Seat();
seat.up();
peugeot.start();
handlebar.left();
handlebar.right();
}
}
Output konsol:
Seat up!
Let's go!
Steer left!
Steer right!
Sekarang apa yang kita lihat tiba-tiba masuk akal! :) Kami mencipta objek basikal. Kami mencipta dua "subobjek" basikal — bar hendal dan tempat duduk. Kami menaikkan tempat duduk untuk keselesaan dan kami pergi: mengayuh dan mengemudi mengikut keperluan! :) Kaedah yang kita perlukan dipanggil pada objek yang sesuai. Semuanya mudah dan selesa. Dalam contoh ini, mengasingkan bar hendal dan tempat duduk meningkatkan enkapsulasi (kami menyembunyikan data tentang bahagian basikal di dalam kelas yang berkaitan) dan membolehkan kami membuat abstraksi yang lebih terperinci. Sekarang mari kita lihat situasi yang berbeza. Katakan kita ingin mencipta program yang menyerupai kedai basikal dan alat ganti untuk basikal. 
-
Objek kelas dalam tidak boleh wujud tanpa objek kelas luar.
Ini masuk akal: inilah sebabnya kami membuat kelas
Seat
danHandlebar
kelas dalaman dalam program kami — supaya kami tidak mendapat hendal dan tempat duduk yatim piatu.Kod ini tidak menyusun:
public static void main(String[] args) { Handlebar handlebar = new Handlebar(); }
Satu lagi ciri penting berikut dari ini:
-
Objek kelas dalam mempunyai akses kepada pembolehubah kelas luar.
Sebagai contoh, mari tambah
int seatPostDiameter
pembolehubah (mewakili diameter tiang tempat duduk) padaBicycle
kelas kita.Kemudian dalam
Seat
kelas dalaman, kita boleh menciptadisplaySeatProperties()
kaedah yang memaparkan sifat tempat duduk:public class Bicycle { private String model; private int weight; private int seatPostDiameter; public Bicycle(String model, int weight, int seatPostDiameter) { this.model = model; this.weight = weight; this.seatPostDiameter = seatPostDiameter; } public void start() { System.out.println("Let's go!"); } public class Seat { public void up() { System.out.println("Seat up!"); } public void down() { System.out.println("Seat down!"); } public void displaySeatProperties() { System.out.println("Seat properties: seatpost diameter = " + Bicycle.this.seatPostDiameter); } } }
Dan kini kami boleh memaparkan maklumat ini dalam program kami:
public class Main { public static void main(String[] args) { Bicycle bicycle = new Bicycle("Peugeot", 120, 40); Bicycle.Seat seat = bicycle.new Seat(); seat.displaySeatProperties(); } }
Output konsol:
Seat properties: seatpost diameter = 40
Catatan:pembolehubah baharu diisytiharkan dengan pengubah suai akses yang paling ketat (
private
). Dan kelas dalaman masih mempunyai akses! -
Objek kelas dalam tidak boleh dibuat dalam kaedah statik kelas luar.
Ini dijelaskan oleh ciri khusus tentang cara kelas dalaman dianjurkan. Kelas dalaman boleh mempunyai pembina dengan parameter, atau hanya pembina lalai. Tetapi tidak kira, apabila kita mencipta objek kelas dalam, rujukan kepada objek kelas luar secara halimunan dihantar kepada objek yang dicipta kelas dalam. Lagipun, kehadiran rujukan objek sedemikian adalah keperluan mutlak. Jika tidak, kami tidak akan dapat mencipta objek kelas dalam.
Tetapi jika kaedah kelas luar adalah statik, maka kita mungkin tidak mempunyai objek kelas luar! Dan ini akan menjadi pelanggaran logik cara kelas dalaman berfungsi. Dalam keadaan ini, pengkompil akan menghasilkan ralat:
public static Seat createSeat() { // Bicycle.this cannot be referenced from a static context return new Seat(); }
-
Kelas dalaman tidak boleh mengandungi pembolehubah dan kaedah statik.
Logiknya adalah sama: kaedah statik dan pembolehubah boleh wujud dan dipanggil atau dirujuk walaupun tanpa objek.
Tetapi tanpa objek kelas luar, kita tidak akan mempunyai akses kepada kelas dalam.
Percanggahan yang jelas! Inilah sebabnya mengapa pembolehubah statik dan kaedah tidak dibenarkan dalam kelas dalaman.
Pengkompil akan menghasilkan ralat jika anda cuba menciptanya:
public class Bicycle { private int weight; public class Seat { // An inner class cannot have static declarations public static void displaySeatProperties() { System.out.println("Seat properties: seatpost diameter = " + Bicycle.this.seatPostDiameter); } } }
-
Apabila mencipta objek kelas dalam, pengubah suai aksesnya adalah penting.
Kelas dalaman boleh ditandakan dengan pengubah suai akses standard:
public
,private
,protected
, danpackage private
.Mengapa perkara ini penting?
Ini mempengaruhi tempat kita boleh mencipta contoh kelas dalaman dalam program kita.
Jika
Seat
kelas kami diisytiharkan sebagaipublic
, kami boleh menciptaSeat
objek dalam mana-mana kelas lain. Satu-satunya keperluan ialah objek kelas luar juga mesti wujud.By the way, kami sudah melakukan ini di sini:
public class Main { public static void main(String[] args) { Bicycle peugeot = new Bicycle("Peugeot", 120); Bicycle.Handlebar handlebar = peugeot.new Handlebar(); Bicycle.Seat seat = peugeot.new Seat(); seat.up(); peugeot.start(); handlebar.left(); handlebar.right(); } }
Kami dengan mudah mendapat akses ke
Handlebar
kelas dalaman daripadaMain
kelas.Jika kita mengisytiharkan kelas dalam sebagai
private
, kita akan dapat mencipta objek hanya di dalam kelas luar.Kami tidak lagi boleh mencipta
Seat
objek "di luar":private class Seat { // Methods } public class Main { public static void main(String[] args) { Bicycle bicycle = new Bicycle("Peugeot", 120, 40); // Bicycle.Seat has private access in Bicycle Bicycle.Seat seat = bicycle.new Seat(); } }
Anda mungkin sudah faham logiknya :)
-
Pengubah suai akses untuk kelas dalaman berfungsi sama seperti pembolehubah biasa.
Pengubah
protected
suai menyediakan akses kepada pembolehubah contoh dalam subkelas dan kelas yang berada dalam pakej yang sama.protected
juga berfungsi untuk kelas dalaman. Kita boleh menciptaprotected
objek kelas dalam:- dalam kelas luar;
- dalam subkelasnya;
- dalam kelas yang berada dalam pakej yang sama.
Jika kelas dalam tidak mempunyai pengubah akses (
package private
), objek kelas dalam boleh dibuat:- dalam kelas luar;
- dalam kelas yang berada dalam pakej yang sama.
Anda telah biasa dengan pengubah suai untuk masa yang lama, jadi tiada masalah di sini.
GO TO FULL VERSION