Javaには4種類のネストされたクラスがあります:
静的ネストクラスは、外部クラスの非静的メンバーに直接アクセスすることができません。これは別のクラスとしてコンパイルされ、そのインスタンスは外部オブジェクトへの隠れた参照を保持しません。
内部クラス(non-static)は、外部オブジェクトへの暗黙の参照を保持し、そのフィールドにアクセスできます。このクラスは、外部オブジェクトのデータにアクセスするリスナーやイテレーターの実装に頻繁に使用されます。
class Outer { static class Nested { // static void foo() {} } class Inner { // non-static void bar() { System.out.println(value); // 外部クラスのフィールドにアクセス } } int value = 42; }
外部クラスの状態にアクセスする必要がない場合、外部クラスに意味的に関連するユーティリティまたは補助的な構文のためにstatic nested classを使用してください。外部クラスの非静的メンバーに直接アクセスする必要がある場合は、inner classを使用してください。
質問: 「static nested classは外部クラスのインスタンスの非静的フィールドに直接アクセスできますか?」
回答: いいえ、static nested classは外部クラスのインスタンスの非静的フィールドやメソッドに直接アクセスすることはできません。外部クラスのオブジェクトへの参照を保持していないためです。
逸話
データをキャッシュするライブラリで、外部クラスの設定にアクセスできると思ってstatic nested classを使用していた。アクセスを試みたところ、コンパイルエラーが発生し、内部クラスは非静的フィールドを見えなかったため、アーキテクチャを変更せざるを得なかった。
逸話
グラフィカルアプリケーションのインターフェースで、定数のためにinner classを使用した結果、外部オブジェクトへの余分な暗黙の参照が発生した。これにより、ガベージコレクタがメモリを適切にクリーンアップできず、メモリリークが発生した。
逸話
内部クラスを含むコレクションのシリアル化中に問題が発生した。inner classは親オブジェクトへの参照を保持しており、シリアル化中に依存関係のツリー全体がシリアル化され、プロセスが著しく遅くなり、結果のサイズも増加した。static nested classに変更した後は問題が解消された。