🎯

【Java】クラス解説39・匿名クラス

2024/07/15に公開

匿名クラス

匿名クラスとはクラス名の定義を行わず、インスタンスの生成を持って匿名クラスを定義するものです。
また、匿名クラスは一度しか使えませんが、新しいクラスを作成する手間を省き、コードを簡潔に保つのに役立ちます。
下記では、同じ結果となるコードを、内部クラス・ローカルクラス・匿名クラスの各々を使って記述しますので、比較して理解を深めていきたいと思います。


内部クラスのコード例

public class Main {
    public static void main(String[] args) {
        // 外部クラスのインスタンスを生成
        Plant plant = new Plant();
        // 外部クラスのインスタンスからcreateメソッドを呼出
        plant.create();
    }
}

// 外部クラスを定義
class Plant {
    // インターフェイスFuziを実装した内部クラスSakuraを定義
    class Sakura implements Fuzi {
        // インターフェイスFuziのprintメソッドをオーバーライド
        public void print() {
            System.out.println("サクラ");
        }
    }
    
    // createメソッドを定義
    void create() {
        // 外部クラスから内部クラスのインスタンスを生成
        Sakura sakura = new Sakura();
        // 外部クラスからprintメソッドを呼出
        sakura.print();
    }
}

// インターフェイスFuziを定義
interface Fuzi {
    // 抽象メソッドprint定義
    void print();
}

内部クラスについては、下記を参考にしてください。

https://zenn.dev/goriki/articles/075-inner-classe

ローカルクラスのコード例

public class Main {
    public static void main(String[] args) {
        // 外部クラスのインスタンスを生成
        Plant plant = new Plant();
        // 外部クラスのインスタンスからcreateメソッドを呼出
        plant.create();
    }
}

// 外部クラスを定義
class Plant {
    // createメソッドを定義
    void create() {
        // インターフェイスFuziを実装したローカルクラスSakuraを定義
        class Sakura implements Fuzi {
            // インターフェイスFuziのprintメソッドをオーバーライド
            public void print() {
                System.out.println("サクラ");
            }
        }
        // 外部クラスから内部クラスのインスタンスを生成
        Sakura sakura = new Sakura();
        // 外部クラスからprintメソッドを呼び出し
        sakura.print();
    }
}

// インターフェイスFuziを定義
interface Fuzi {
    // 処理内容を実装しないprintメソッド定義
    void print();
}

ローカルクラスについては、下記を参考にしてください。

https://zenn.dev/goriki/articles/076-local-class

匿名クラスのコード例1

public class Main {
    public static void main(String[] args) {
        // 外部クラスのインスタンスを生成
        Plant plant = new Plant();
        // 外部クラスのインスタンスからcreateメソッドを呼出
        plant.create();
    }
}

// 外部クラスを定義
class Plant {
    // createメソッドを定義
    void create() {
        // インターフェイスFuziを実装した匿名クラスを定義し、同時にインスタンスを生成
        Fuzi sakura = new Fuzi() {
            // インターフェイスFuziのprintメソッドをオーバーライド
            public void print() {
                System.out.println("サクラ");
            }
        };
        // 外部クラスからprintメソッドを呼び出し
        sakura.print();
    }
}

// インターフェイスFuziを定義
interface Fuzi {
    // 処理内容を実装しないprintメソッド定義
    void print();
}

上記は、匿名クラスのインスタンスを変数に代入する方法です。
下記は、匿名クラスのインスタンスをメソッドの呼び出し時に直接渡す方法を紹介します。

匿名クラスのコード例2

public class Main {
    public static void main(String[] args) {
        Plant plant = new Plant();
        plant.create();
    }
}

class Plant {
    void create() {
        // callPrintメソッドを呼び出す時に、匿名クラスのインスタンスを渡す。
        callPrint(new Fuzi() {
            public void print() {
                System.out.println("サクラ");
            }
        });
    }
    
    // callprintメソッドを定義して、匿名クラスのインスタンスを受け取る。
    void callPrint(Fuzi fuzi) {
        fuzi.print();
    }
}

interface Fuzi {
    void print();
}

上記4つのコードの出力結果は、いずれもサクラとなります。


ここからは、匿名クラスの他の使い方について紹介します。

外部クラスのインスタンス変数にアクセスするコード例

public class Main {
    public static void main(String[] args) {
        Plant plant = new Plant();
        plant.create();
    }
}

class Plant {
    // 外部クラスのインスタンス変数
    private String name = "フジ";

    void create() {
        // 匿名クラス
        callPrint(new Fuzi() {
            public void print() {
                // 匿名クラスから外部クラスのインスタンス変数にアクセス
                System.out.println(name);
            }
        });
    }
    
    void callPrint(Fuzi fuzi) {
        fuzi.print();
    }
}

interface Fuzi {
    void print();
}

出力結果は、フジとなります。


外部クラスのインスタンスメソッドにアクセスするコード例

public class Main {
    public static void main(String[] args) {
        Plant plant = new Plant();
        plant.create();
    }
}

class Plant {
    private String name = "フジ";

    void create() {
        // 匿名クラス
        callPrint(new Fuzi() {
            public void print() {
                System.out.println(name);
                // 匿名クラスから外部クラスのインスタンスメソッドにアクセス
                printNumber();
            }
        });
    }
    
    void callPrint(Fuzi fuzi) {
        fuzi.print();
    }
    
    // 外部クラスのインスタンスメソッド
    private void printNumber() {
        System.out.println("23");
    }
}

interface Fuzi {
    void print();
}

出力結果は、フジ23になります。


ローカル変数にアクセスするコード例

匿名クラスでは、ローカルクラスと同様に、そのクラスが定義されているメソッドやブロックのfinalまたは実質的にfinalなローカル変数にのみアクセスできます。

public class Main {
    public static void main(String[] args) {
        Plant plant = new Plant();
        plant.create();
    }
}

class Plant {
    void create() {
        // ローカル変数
        final String name = "フジ";
        // 匿名クラス
        callPrint(new Fuzi() {
            public void print() {
                // 匿名クラスからローカル変数にアクセス
                System.out.println(name);
            }
        });
    }
    
    void callPrint(Fuzi fuzi) {
        fuzi.print();
    }
}

interface Fuzi {
    void print();
}

出力結果は、フジとなります。


Discussion