首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 內部類完全指南:成員、局部、匿名、靜態嵌套類與編譯器實現原理

     編輯:Java 綜合教學

為什麼需要內部類?

  1. 訪問外部私有成員:內部類可無限制訪問外部類所有成員(含 private)。
  2. 封裝隱藏:對同包其他類不可見,實現更細粒度的封裝。
  3. 回調便利:匿名內部類實現單方法介面極其簡潔(Lambda 前身)。

四大類型對比

類型定義位置訪問外部實例典型用途語法關鍵字
成員內部類類內部、方法外隱式持有 Outer.this邏輯強綁定、多實例共享外部狀態無
靜態嵌套類類內部、方法外無(無 Outer.this)工具類、數據容器、獨立邏輯static
局部內部類方法/代碼塊內持有外部實例 + 複製 final 變量僅在單方法內使用、實現介面無
匿名內部類表達式中同局部類一次性實現介面/繼承類、事件監聽new Interface() { ... }

成員內部類深度解析

public class Outer {
    private int value = 10;
    public class Inner {
        public void print() { System.out.println(value); // 直接訪問 private }
    }
    public void demo() { new Inner().print(); }
}
// 編譯器生成:
// class Outer$Inner { final Outer this$0; Outer$Inner(Outer o){ this$0=o; } void print(){ System.out.println(this$0.value); } }
  • 外部實例引用名為 this$0(合成字段),構造器由編譯器注入。
  • 外部創建:Outer.Inner in = outer.new Inner(); 或外部類方法內 new Inner() 隱含 this。
  • 訪問外部 this:Outer.this.value。

局部內部類與 final 變量捕獲

public void start(final boolean beep) {
    class TimerTask implements Runnable {
        public void run() { if (beep) Toolkit.getDefaultToolkit().beep(); }
    }
    new Thread(new TimerTask()).start();
}
// 編譯器生成:class Outer$1TimerTask { final boolean val$beep; ... }
// beep 被複製到構造器參數並存入 val$beep,保證生命週期超過方法棧幀
  • JDK 8+ effectively final:變量未重新賦值即可隱式 final,無需寫 final。
  • 需修改捕獲變量?用單元素數組 final int[] counter = {0}; 修改 counter[0]++。

匿名內部類:Lambda 前身

button.addActionListener(new ActionListener() {
    @Override public void actionPerformed(ActionEvent e) { System.out.println("click"); }
});
// 語法:new SuperType(args) { body }
// SuperType 為介面 → 實現;為類 → 繼承。
// 無構造器,若需參數用實例初始化塊 { }。

靜態嵌套類:獨立的內部類

public class ArrayAlg {
    public static class Pair { // 靜態嵌套類
        private double first, second;
        public Pair(double f, double s) { first=f; second=s; }
        public double getFirst() { return first; }
    }
    public static Pair minmax(double[] a) { ... return new Pair(min, max); }
}
// 用法:ArrayAlg.Pair p = ArrayAlg.minmax(data);
  • 無 Outer.this,可獨立實例化:new Outer.StaticNested()。
  • 常用於「邏輯歸屬外部類但無需外部實例」的場景(如 Builder、Node、Entry)。

編譯器視角:內部類是語法糖

  • JVM 只知道普通類,Outer$Inner.class 即內部類字節碼文件。
  • 私有訪問通過合成 access$0(Outer) 靜態方法實現(字節碼層面 package-private)。
  • 反編譯工具(javap -private)可見合成字段/構造器/訪問器方法。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved