內部類是 Java 物件導向特性的重要延伸,允許在類內部定義類,實現邏輯封裝與外部類成員的無縫訪問。本文系統梳理四大內部類類型、實例化語法、訪問規則與實戰注意事項。
| 類型 | 定義位置 | 修飾符支援 | 典型應用場景 |
|---|---|---|---|
| 成員內部類 | 類內部、方法外部 | public/protected/private/static | 與外部類強綁定的實體,如節點類 |
| 局部內部類 | 方法/程式碼塊內部 | 無修飾符(隱含 final) | 方法內邏輯封裝,實現介面回調 |
| 匿名內部類 | 表達式中現場定義 | 無名稱,隱含 final | 單次使用的介面實現/抽象類子類 |
| 靜態內部類 | 類內部、方法外部 | static | 獨立於外部類實例的工具類、Builder 模式 |
class Outer {
private int outerField = 111;
class Inner {
private int innerField = 222;
public void print() {
System.out.println("外部類私有字段: " + outerField); // 直接訪問
System.out.println("內部類私有字段: " + innerField);
}
}
}
// 使用方式
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // 必須先有外部類實例
inner.print();
// 方式一:外部類實例.new 內部類()
Outer.Inner inner1 = outer.new Inner();
// 方式二:在外部類非靜態方法中直接 new Inner()
class Outer {
public Inner createInner() { return new Inner(); }
}
// 方式三:靜態導入(罕用)
import com.example.Outer.Inner;
Inner inner3 = outer.new Inner();
class Outer {
private int value = 10;
class Inner {
private int value = 20;
public void show() {
System.out.println("內部類 value: " + this.value); // 20
System.out.println("外部類 value: " + Outer.this.value); // 10
}
}
}
定義在方法/建構子/程式碼塊中,僅在該作用域可見。關鍵限制:只能訪問被 final 或「實際上 final」的區域變數(Java 8+ 自動推斷)。
class Demo {
final int constant = 10; // 成員變數無限制
public void method(final String param) { // 參數需 final
class LocalInner {
public void print() {
System.out.println(constant); // OK
System.out.println(param); // OK
}
}
new LocalInner().print();
}
}
加上 static 修飾符後,不再依賴外部類實例,等同於頂層類但享有封裝優勢。無法訪問外部類非靜態成員。
class Outer {
private static String staticField = "靜態字段";
static class StaticInner {
public void accessStatic() {
System.out.println(staticField); // 僅能訪問靜態成員
}
}
}
// 直接實例化,無需外部類對象
Outer.StaticInner si = new Outer.StaticInner();
si.accessStatic();
無名稱、單次使用、必須繼承類或實現介面。常用於事件監聽、執行緒建立、Comparator 實現等場景。
abstract class Animal {
public abstract void sound();
}
public class Test {
public static void main(String[] args) {
// 現場實現抽象類
Animal cat = new Animal() {
@Override
public void sound() { System.out.println("喵~"); }
};
cat.sound();
// 實現介面(Runnable 範例)
new Thread(new Runnable() {
@Override public void run() { System.out.println("執行緒運行"); }
}).start();
}
}
outer.new Inner())。private/protected 修飾,頂層類不可。StringBuilder、HttpClient.Builder)。