在 Java 面向對象程式設計中,我們可以在一個類的內部定義另一個類,這類稱為嵌套類。嵌套類主要分為兩類:靜態嵌套類和非靜態嵌套類(即內部類)。內部類是 Java 語言的重要特性,它幾乎可以出現在外部類的任何位置:與實例變量同級、方法內部,甚至作為表達式的一部分。
普通內部類持有對外部類實例的隱式引用,因此可以直接訪問外部類的所有成員(包括私有成員),外部類也同樣可以訪問內部類的私有成員。
// 外部類
class OutterClass {
// 內部類
public class InnerClass {
private int i = 0;
public int getInt() {
return i;
}
}
public void proc() {
InnerClass inClass = new InnerClass();
System.out.println(inClass.getInt());
}
}
public class Main {
public static void main(String[] args) {
OutterClass outClass = new OutterClass();
outClass.proc();
}
}
class OutterClass {
private int mOut = 10;
public class InnerClass {
private int mIn = 0;
public void printOutPrivate() {
// 直接訪問外部類私有成員
System.out.println(mOut);
}
}
public void printInPrivate() {
InnerClass inClass = new InnerClass();
// 直接訪問內部類私有成員
System.out.println(inClass.mIn);
}
}
當內外部類存在同名成員時,使用 OuterClass.this.member 訪問外部類成員:
class OutterClass {
private int mMem = 10;
public class InnerClass {
private int mMem = 0;
public void printOutPrivate() {
System.out.println(OutterClass.this.mMem); // 訪問外部類的 mMem
}
}
}
必須先創建外部類實例,再通過外部類實例創建內部類:
OutterClass outClass = new OutterClass();
OutterClass.InnerClass inClass = outClass.new InnerClass();
或在外部類中提供工廠方法:
public InnerClass newInnerClass() {
return new InnerClass();
}
// 使用
OutterClass.InnerClass inClass = outClass.newInnerClass();
在內部類前加 static 修飾符即成為靜態內部類。它類似於 C++ 的嵌套類,與普通內部類的關鍵區別:
class OutterClass {
private int mMem = 0;
static public class InnerClass {
private int mMem = 0;
public void printOutPrivate() {
// 編譯錯誤:無法訪問外部類實例成員
// System.out.println(OutterClass.this.mMem);
}
}
public void printInPrivate() {
InnerClass inClass = new InnerClass();
System.out.println(inClass.mMem); // 可直接訪問靜態內部類成員
}
}
public class Main {
public static void main(String[] args) {
// 直接創建靜態內部類實例
OutterClass.InnerClass inClass = new OutterClass.InnerClass();
inClass.printOutPrivate();
}
}
定義在方法或代碼塊內部,作用域僅限於該塊。常用於實現接口並作為接口類型返回:
interface Talker {
void Talk();
}
class OutterClass {
public Talker getTalker() {
// 方法內部類實現接口
class SomeTalker implements Talker {
public void Talk() {
System.out.println("hello");
}
}
return new SomeTalker();
}
}
語法:new InterfaceName() {...} 或 new SuperclassName() {...}。無構造函數,若父類構造函數有參數需在創建時傳入。常用於事件監聽器、線程創建等場景:
OutterClass outClass = new OutterClass();
outClass.Talk(new Talker() {
public void Talk() {
System.out.println("hello");
}
});
內部類提供了更好的封裝性,能讓邏輯相關的類組織在一起。普通內部類適合需要訪問外部類實例狀態的場景;靜態內部類適合作為命名空間或工具類;局部/匿名內部類適合一次性使用、實現接口或回調的場景。合理使用內部類能使代碼結構更清晰、耦合度更低。