Java

【クラスの中で定義するクラス】インナークラス

インナークラスとは???

Javaでは、クラス宣言ブロックの中にさらにクラス宣言を書くことがゆるされています。内側に宣言されたクラスのことをインナークラスと言います。インナークラスと言ってもその宣言場所によって3つに分類されます。メンバ(フィールドとメソッド)と同じように、private,protected, publicなどのアクセスレベル修飾子をつけることができます。さらに、インナークラスは、インナークラスが属しているクラスのフィールドやメソッドを参照することができます。つまり、あるクラス内のメンバにアクセスするクラスを宣言する場合にインナークラスを宣言します。そして内部クラスを持つクラスのことをアウタークラスとも言います。

  • メンバクラス

・クラスブロックの中

  • ローカルクラス

・メソッドブロックの中

  • 匿名クラス

・文の中(式の一部)
(親クラス名を指定)

メンバクラス

今までは、、メンバはフィールドとメソッドでしたが、、、、
これからは、そこにメンバクラスも仲間入りです。

staticではない(インスタンス化しないと使用できない)
// 外部クラス
class OuterClass {

    private static String str1 = "OuterClassの変数";
    private String str2 = "hoge"//アクセス可能

    // 内部クラス
    class InnerClass {
        public void innerSample() {
            System.out.println(str1);
        }
    }

    void outerMethod(){
     //外部クラスからのアクセス
     InnerClass ic = new InnerClass();
    }

}//外部クラス終わり
 
public class Main {
        public static void main(String[] args) {
        // 無関係なクラスからのアクセス
        OuterClass.InnerClass ic = new OuterClass.InnerClass();
        ic.innerSample();//OuterClassの変数
    }
 
}

staticで宣言されていないインナークラス単体でnew(インスタンス化)すると、完全に別なクラスとして扱われるために、エラーになります。しかし、staticで宣言されたインナークラスは、実体がそのインナークラスが属するアウタークラスにあるため、インナーククラスをインスタンス化してもエラーにはなりません。ただ、staticで宣言されていないインナークラスでも、アウタークラスのインスタンスがあればnew(インスタンス化)は可能になり、アウタークラスのインスタンスと必ずつながっているため非staticのメンバにもアクセスできるようになります。

staticである(インスタンス化しなくても使える)
// 外部クラス
class OuterClass {
    // staticなフィールド
    private static String str1 = "OuterClassの変数";
    private String str2 = "hoge";//アクセス不可
    
    // staticな内部クラス
    static class InnerClass {
        public void innerSample() {
            System.out.println(str1);
        }
    }

    //外部クラスからのアクセス
    void outerMethod(){  
    InnerClass ic = new InnerClass(); 
    }
}
 
public class Main {
 
    public static void main(String[] args) {
        // 無関係なクラスからのアクセス
        // staticな内部クラスのインスタンスを生成
        OuterClass.InnerClass ic = new OuterClass.InnerClass();
    
        ic.innerSample();//OuterClassの変数
    }
 
}

staticで宣言されたインナークラスは、staticで宣言されたアウタークラスのメンバーにのみアクセスできます。

staticで宣言されたインナークラスは、実体はアウタークラスにあるので、、アウタークラスをインスタンス化した場合、そのアウタークラスのインスタンスとは、繋がっていないので、非staticのメンバにはアクセスできません。staticで宣言されたアウタークラスのメンバの実体は、アウタークラスにあるためアクセスできます。

ローカルクラス

メソッドブロック内で宣言されるクラス定義で、その宣言されたメソッド内でのみ利用可能になります。

public class OuterClass{
    int outerMember;
    void OuterMethod(){
        int a = 10;

        class Inner{
            public void innerMethod(){
            System.out.println("innerMethodです。");
            System.out.println(outerMember);
            }
        }
        Inner ic = new Inner();
        ic.innerMethod();
    }
}
ローカルクラスの特徴

・finalとabstract以外の修飾は行えない(必要がない)
・外部クラスのメンバにアクセス可能
・自身を取り囲むメソッド内のローカル変数についてはfinalがついたものにのみアクセス可能(java8以降では、再代入が行われていないなら暗黙的にfinalとみなされエラーにならない)

匿名クラス

普通のクラスやメンバクラスは、classキーワードでまず宣言してからその後newでインスタンス化してから利用しますが匿名クラスは、宣言と利用を同時に行います。つまり、宣言すると同時にインスタンス化もやっちゃいます。

public class Main{
    public static void main(String[] args){
        Pocket<Object> pocket = new Pocket<Object>();
        System.out.println("使いすてのインスタンスを作りPocketに入れる");
        pocket.put(new Object(){
            String innerFiled;
            void innerMethod(){...}
        });
    }
}

上の例のnew Object(){匿名クラスの内容}にある、Objectと言うのは匿名クラスが継承している親クラスを指定している。

一般化すると

new 匿名クラスの親クラス指定(){
匿名クラスのメンバ定義
}

参考サイト

Qiita-インナークラス・メンバークラス

HatenaBlog-匿名クラスとかローカルクラスとか

<>TECHACADEMYmagazine-匿名クラスの使い方