マイナー・マイナー

隠れた名作の発掘が生きがい。

インナークラスからメンバを利用する際に注意すること


スポンサードリンク

Javaではクラスの中にクラスを定義することができます.しかし,その際のメンバやメソッドへのアクセスがややこしいので,プログラムを書いてみて試してみました.

まず,インナークラスは大きく次の4つに分類されます.
(1)非staticなインナークラス
(2)staticなインナークラス
(3)メソッドローカルなインナークラス
(4)無名クラス


(1)と(2)はメンバに,(3)と(4)はメソッド内に記述します.(1)から(4)で定義されるメソッド内からさまざまメンバにアクセスする際,クラスごとにアクセス可能かどうかを考慮しなければなりません.


アクセスを考慮したインナークラスの実装例を次に示します.コメントアウトしてある部分を外すとエラーが起きます.

public class InnerClassTest {

	public String a = "A";
	static String b = "B";

	class InnerClass1 {
		public String c = "C";
		// static String d = "D";  //エラー (1-A)

		void display1() {
			System.out.println(a);
			System.out.println(b);
			System.out.println(c);
			// System.out.println(d); //エラー (1-A)
		}
	}

	static class InnerClass2 {
		public String c = "C";
		static String d = "D";

		void display2_1() {
			// System.out.println(a); //エラー (2-A)
			System.out.println(b);
			System.out.println(c);
			System.out.println(d);
		}

		static void display2_2() {
			// System.out.println(a); //エラー (2-A)
			System.out.println(b);
			// System.out.println(c); //エラー (2-B)
			System.out.println(d);
		}
	}

	public void method() {
		String c = "C";
		final String d = "D";

		class InnerClass3 {
			String e = "E";

			void display3() {
				System.out.println(a);
				System.out.println(b);
				// System.out.println(c); //エラー (3-A)
				System.out.println(d);    //(3-B)
				System.out.println(e);
			}
		}
		new InnerClass3().display3();
	}

	public static void main(String[] args) {
		// 非staticなインナークラスの利用
		System.out.println("InnerClass1:display1()");
		new InnerClassTest().new InnerClass1().display1();

		// staticなインナークラスの利用(メソッドが非static)
		System.out.println("InnerClass2:display2_1()");
		new InnerClassTest.InnerClass2().display2_1();

		// staticなインナークラスの利用(メソッドがstatic)
		System.out.println("InnerClass2:display2_2()");
		InnerClassTest.InnerClass2.display2_2();

		// メソッドローカルなインナークラスの利用
		System.out.println("InncerClass3:display3()");
		new InnerClassTest().method();

		// 無名クラスの利用
		System.out.println("InncerClass4:display4()");
		String c = "C";
		final String d = "D";
		new Object() {
			String e = "E";

			void display4() {
				// System.out.println(a); //エラー (4-A)
				System.out.println(b);
				// System.out.println(c); //エラー (4-B)
				System.out.println(d);    //(4-C)
				System.out.println(e);
			}
		}.display4();
	}
}


実行結果


InnerClass1:display1()
A
B
C
InnerClass2:display2_1()
B
C
D
InnerClass2:display2_2()
B
D
InncerClass3:display3()
A
B
D
E
InncerClass4:display4()
B
D
E


各インナークラスを利用する際に注意すべきルールは次の通りです.
(1)非staticなインナークラス
(1-A) (1)ではstaticなメンバを宣言できない


(2)staticなインナークラス
(2-A) クラスがstaticなので,publicなメンバにアクセスできない
(2-B) メソッドがstaticなので,publicなメンバにアクセスできない


(3)メソッドローカルなインナークラス
(3-A) 外部で定義されたローカル変数は利用できない
(3-B) finalがついたローカル変数は利用できる


(4)無名クラス
(4-A) メソッドがstaticなので,publicなメンバにアクセスできない
(4-A) 外部で定義されたローカル変数は利用できない
(4-B) finalがついたローカル変数は利用できる