Outer$Inner.class)static 修飾內部類與匿名內部類實戰模式修飾符 class OuterClass {
// 外部類成員
修飾符 class InnerClass {
// 內部類成員
}
}
編譯後生成獨立 .class 文件,文件名格式:OuterClass$InnerClass.class。
定義在類內部、方法外。可使用任意修飾符(含 static)。
public class Outer {
private String info = "外部類私有字段";
// 非靜態成員內部類
class Inner {
void print() {
System.out.println(info); // 直接訪問外部 private
}
}
// 靜態成員內部類(靜態嵌套類)
static class StaticInner {
void print() {
// System.out.println(info); // 編譯錯誤
System.out.println("靜態內部類");
}
}
public void test() {
new Inner().print(); // 內部直接實例化
}
}
// 外部調用
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // 非靜態需外部實例
Outer.StaticInner staticInner = new Outer.StaticInner(); // 靜態直接 new
定義在方法/初始化塊內,作用域僅限該塊。只能訪問 final 或 實際上 final 的局部變量。
public class MethodInnerDemo {
private String field = "字段";
public void method() {
final String localFinal = "局部final";
String localEffectiveFinal = "實際final"; // Java 8+
class LocalInner {
void print() {
System.out.println(field); // 訪問字段
System.out.println(localFinal); // 訪問 final 局部變量
System.out.println(localEffectiveFinal); // 訪問實際 final
}
}
new LocalInner().print(); // 必須在方法內創建
}
}
原理:局部變量存棧,方法結束即銷毀;內部類對象存堆,可能長期存活。為防止訪問已銷毀變量,編譯器將 final 變量值複製到內部類構造器中(實際為常量池引用)。
無類名,同時聲明並創建實例。前提:繼承類或實現接口。大量用於函數式接口實現(Java 8 前)。
// 1. 實現接口
Runnable r = new Runnable() {
@Override public void run() { System.out.println("匿名實現 Runnable"); }
};
// 2. 繼承抽象類
abstract class Animal { abstract void sound(); }
Animal cat = new Animal() { void sound() { System.out.println("Meow"); } };
// 3. 方法參數傳遞(典型場景)
public void execute(Runnable task) { task.run(); }
execute(new Runnable() { public void run() { System.out.println("執行任務"); } });
// 4. 現代替代:Lambda 表達式(僅適用函數式接口)
execute(() -> System.out.println("Lambda 更簡潔"));
| 維度 | 優點 | 缺點 |
|---|---|---|
| 封裝性 | 隱藏實現細節,高內聚 | 增加類文件數量,結構複雜 | 訪問權限 | 直接訪問外部私有成員 | 非靜態內部類隱式持有外部引用,易導致內存洩漏 |
| 多重繼承 | 每個內部類可獨立繼承/實現,變相實現多重繼承 | 代碼閱讀需跳轉,調試堆疊深 |
| 回調場景 | 匿名內部類簡化單次使用的接口實現 | Java 8+ Lambda 更優雅,匿名類漸成遺產 |
class Outer {
private static String staticField = "靜態字段";
private String instanceField = "實例字段";
static class StaticNested {
void access() {
System.out.println(staticField); // ✅ 可訪問靜態
// System.out.println(instanceField); // ❌ 編譯錯誤
}
}
}
// 調用方式
Outer.StaticNested nested = new Outer.StaticNested();
nested.access();
關鍵差異:靜態內部類不持有 Outer.this 引用,獨立於外部類實例,可序列化、無內存洩漏風險。
static class 或 LambdawriteReplace