JavaのNestedClassについて

(更新: 2025年12月28日)
  • Web
  • Java

この記事の概要

  • NestedClassの書き方や使うメリットを紹介するよ
  • 関連するクラスを1箇所にまとめたり、カプセル化で実装を隠蔽したり出来るよ

NestedClassの利点

一箇所でしか使用されないクラスを論理的にグループ化する

OuterClassの内部に更にデータ構造がある場合、OuterClassの中に作る方がデータをまとめることが出来るため合理的です。 また、内部のInnerClassstaticで定義することで、OuterClassのインスタンスを作成せずにInnerClassだけをインスタンス化することが可能になります。 下記の例ではrecord型を使うとより簡潔に記述可能です。

public class OuterClass {
    private final String outerField;

    public OuterClass(String outerField) {
        this.outerField = outerField;
    }

    String getOuterField() {
        return outerField;
    }

    
    static class InnerClass {
        private final String innerField;

        public InnerClass(String innerField) {
            this.innerField = innerField;
        }

        String getInnerField() {
            return innerField;
        }
    }

    // recordクラスでも表現可能。 
    // record InnerClass(String innerField) {
    // }

    public static void main(String[] args) {
        OuterClass outer = new OuterClass("Outer Value");
        InnerClass inner = new InnerClass("Inner Value");

        System.out.println("Outer Field: " + outer.getOuterField());
        System.out.println("Inner Field: " + inner.getInnerField());

    }
}

カプセル化を強化する

下記のクラスBEncapsulatedAクラスのprivateメンバにアクセス出来ます。 通常、別のクラスからprivateフィールドにアクセスできませんが、ネストしたクラスは外部クラスのprivateメンバにアクセスできます。 また、クラスBprivateで宣言しているため、外部からはクラスBの存在自体が見えません。外部にはgetSecretViaB()というメソッドだけを公開し、内部でクラスBを使っていることは隠蔽されています。

観点のまとめ

観点説明
実装の隠蔽内部でどのように処理しているか外部に知らせない
変更への耐性クラスBの実装を変更しても外部に影響しない
責務の分離特定の処理を専用クラスに委譲しつつ、外部APIはシンプルに保つ
public class EncapsulatedA {
    private int secretValue;

    public EncapsulatedA(int value) {
        this.secretValue = value;
    }

    // BはAのprivateメンバにアクセス可能
    private static class B {
        int revealSecret(EncapsulatedA a) {
            return a.secretValue;
        }
    }

    // 外部にBを公開せず、Aのメソッド経由でBの機能を提供
    public int getSecretViaB() {
        B b = new B();
        return b.revealSecret(this);
    }

    public static void main(String[] args) {
        EncapsulatedA a = new EncapsulatedA(42);
        System.out.println("Secret Value via B: " + a.getSecretViaB());
    }
}

まとめ

  • NestedClassの書き方や使うメリットを紹介したよ
  • 関連するクラスを1箇所にまとめたり、カプセル化で実装を隠蔽したり出来るよ
  • privateで隠しているクラス、隠しているクラスにアクセスするメソッドを実装したクラス、そのクラスを作成してprivateフィールドにアクセスなど責務を分けて実装できるよ

参考

https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html