Java 速習チュートリアル

Java インナークラス

1. Java インナークラス(内部クラス)

Javaでは、クラスをネスト(入れ子)にすること、つまり「クラスの中にクラスを定義」することが可能です。

ネストされたクラスの目的は、密接に関連するクラスをグループ化することにあります。これにより、コードのリーダブル(可読性)とメンテナビリティ(保守性)が向上します。

インナークラスにアクセスするには、まず外部クラス(Outer class)のオブジェクトを作成し、その後にインナークラス(Inner class)のオブジェクトを作成します。

例:

class OuterClass {
  int x = 10;

  class InnerClass {
    int y = 5;
  }
}

public class Main {
  public static void main(String[] args) {
    OuterClass myOuter = new OuterClass();
    OuterClass.InnerClass myInner = myOuter.new InnerClass();
    System.out.println(myInner.y + myOuter.x);
  }
}
// 出力: 15 (5 + 10)

2. private なインナークラス

「通常の」クラスとは異なり、インナークラスには privateprotected の修飾子を付与することができます。外部のオブジェクトからインナークラスにアクセスさせたくない場合は、クラスを private として宣言します。

例:

class OuterClass {
  int x = 10;

  private class InnerClass {
    int y = 5;
  }
}

public class Main {
  public static void main(String[] args) {
    OuterClass myOuter = new OuterClass();
    OuterClass.InnerClass myInner = myOuter.new InnerClass();
    System.out.println(myInner.y + myOuter.x);
  }
}

外部クラスから private なインナークラスにアクセスしようとすると、以下のようなコンパイルエラーが発生します:

Main.java:13: error: OuterClass.InnerClass has private access in OuterClass
    OuterClass.InnerClass myInner = myOuter.new InnerClass();
              ^

3. static なインナークラス

インナークラスを static として宣言することもできます。この場合、外部クラスのオブジェクトを作成せずにインナークラスへアクセスすることが可能です。

例:

class OuterClass {
  int x = 10;

  static class InnerClass {
    int y = 5;
  }
}

public class Main {
  public static void main(String[] args) {
    OuterClass.InnerClass myInner = new OuterClass.InnerClass();
    System.out.println(myInner.y);
  }
}
// 出力: 5

注記: static な属性(フィールド)やメソッドと同様に、static なインナークラスは外部クラスのメンバ(インスタンス変数やインスタンスメソッド)に直接アクセスすることはできません。

4. インナークラスから外部クラスへのアクセス

インナークラスの大きな利点の一つは、外部クラスの属性やメソッドにアクセスできることです。

例:

class OuterClass {
  int x = 10;

  class InnerClass {
    public int myInnerMethod() {
      return x; // 外部クラスの属性xにアクセス
    }
  }
}

public class Main {
  public static void main(String[] args) {
    OuterClass myOuter = new OuterClass();
    OuterClass.InnerClass myInner = myOuter.new InnerClass();
    System.out.println(myInner.myInnerMethod());
  }
}
// 出力: 10