巢狀和內部類

術語和分類

Java 語言規範(JLS)按如下方式對不同型別的 Java 類進行分類:

一個頂層類是一類,是不是一個巢狀類。

一個巢狀類是任何類,其宣告另一個類或介面的主體內發生。

一個內部類是沒有明確或隱含宣告為靜態的巢狀類。

內部類可以是非靜態成員類本地類匿名類。介面的成員類是隱式靜態的,因此永遠不會被視為內部類。

在實踐中,程式設計師引用包含內部類作為外部類的頂級類。此外,還有一種傾向,即使用巢狀類僅引用(顯式或隱式)靜態巢狀類。

請注意,匿名內部類和 lambdas 之間存在密切關係,但 lambdas 是類。

語義差異

  • 頂級類是基礎案例。它們對程式的其他部分是可見的,受基於訪問修飾符語義的正常可見性規則的約束。如果是非抽象的,則可以通過任何基於訪問修飾符可見相關建構函式的程式碼來例項化它們。

  • 靜態巢狀類遵循與頂級類相同的訪問和例項化規則,但有兩個例外:

    • 巢狀類可以宣告為 private,這使得它在封閉的頂級類之外無法訪問。
    • 巢狀類可以訪問封閉頂級類的 private 成員及其所有測試類。

    這使得靜態巢狀類在需要在緊密抽象邊界內表示多個實體型別時非常有用; 例如,當巢狀類用於隱藏實現細節時。

  • 內部類新增了訪問在封閉範圍中宣告的非靜態變數的功能:

    • 非靜態成員類可以引用例項變數。
    • 本地類(在方法中宣告)也可以引用方法的區域性變數,前提是它們是 final。 (對於 Java 8 及更高版本,它們可以是最終的。)
    • 匿名內部類可以在類或方法中宣告,並且可以根據相同的規則訪問變數。

    內部類例項可以引用封閉類例項中的變數這一事實對例項化有影響。具體而言,當建立內部類的例項時,必須隱式或顯式地提供封閉例項。