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がついたローカル変数は利用できる