【Java】匿名クラスとラムダ式〜インターフェースの実装〜

# はじめに
RecursionというCS学習サービスのCS上級コースを学習中に、匿名クラスについて調べました。今回の記事では、匿名クラスの特徴と実装方法、そして、匿名クラスをラムダ式で書き換える方法についてまとめていきます。

# 匿名クラス
匿名クラスは名前を持たないクラスで、**クラスの宣言**と**インスタンス化**を同時に行うことを可能にします。これにより一度しか使用しないインターフェースや抽象クラスの実装を簡潔に行うことが可能になります。
＊匿名クラスは、クラスを継承するか、インターフェースを実装しますが、今回の例では、インターフェースの実装に焦点を当てていきます。

## 特徴
1. 名前を持たないインナークラス（名前がないのでインスタンスを生成するために使用できない。別のクラスの内部で宣言を行う）
1. 名前を持たないから再利用できない
1. 使用時には、匿名クラスの宣言とインスタンス化を行う
1.  一度に一つのインターフェースのみを実装することができる


# 匿名クラスを使用しないインターフェースの実装
一般的なインターフェースの宣言とその実装クラスの実装を行なっていきます。このように実装することで、他クラスでクラス・メソッドの再利用が可能となります。
```java:Demo1.java
interface Example{
    public void display();  // 抽象メソッド
}

class ExampleImpl implements Example{  // 実装クラスで抽象メソッドの実装を提供
    public void display(){
        System.out.println("Hello World!");
    }
}

public class Demo1 {
    public static void main(String[] args){
        Example example = new ExampleImpl();  // ポリモーフィズムの概念
        example.display();  // Hello World!
        new ExampleImpl().display();  // Hello World!
    }
}
```
# 匿名クラスを使用する場合（１）
クラス・関数を再利用することを想定していない場合、その場で宣言し利用することができます。イメージとしては、使い捨てのイメージでしょうか。

```java:Demo2.java
// 関数型インターフェースであることを宣言。省略可能。
// 関数型インターフェース：抽象メソッドを一つだけ持つインターフェース
@FunctionalInterface 
interface Example{
    public void display();  // 抽象メソッド
}

public class Demo2 {
    public static void main(String[] args){
        // インターフェースを実装する匿名クラス
        // 匿名クラスのインスタンスをexample変数に格納
        Example example = new Example(){
            // 抽象メソッドの実装を提供
            @Override
            public void display() {
                System.out.println("Hello World!");
            }
        };

        // その場でメソッドの実行
        example.display();  // Hello World!
    }
}
```
この匿名クラスは、Exampleインターフェースを実装し、displayメソッドの実装を提供します。作成された匿名クラスのオブジェクトへの参照がexample変数に格納されます。
匿名クラスは名前を持たないため再利用できません。また、匿名クラスの名前は、コンパイラによって決定されます。

# 匿名クラスを使用する場合（２）
また、匿名クラスのインスタンスを変数に格納せずに、以下のようにメソッドを実行することも可能です。

```java:Demo2.java
@FunctionalInterface // 関数型インターフェースであることを宣言。省略可能。
interface Example{
    public void display();
}

public class Demo2 {
    public static void main(String[] args){
        // 変数に格納しない
        new Example(){ 
            // 抽象メソッドの実装を提供
            @Override
            public void display() {
                System.out.println("Hello World!");
            }
        }.display();  // Hello World!
    }
}

```


# 匿名クラスをラムダ式で書き換える
ラムダ式を使用することで、匿名クラスの実装をより簡潔に記述することができます。
＊インターフェースが抽象メソッドを一つだけ持つ場合、つまり関数型インターフェースの場合に、ラムダ式での実装が可能となります。
```java:Demo3.java
interface Example{
    public void display();
}

public class Demo3 {
    public static void main(String[] args){
        // ラムダ式を使用する
        // 匿名クラスの実装を簡単に記述できる
        Example example = () -> System.out.println("Hello World!");
        example.display();  // Hello Wolrd!!
    }
}
```

# おわりに
今回は匿名クラスの実装方法と、匿名クラスをラムダ式に変換する方法についてまとめました。今後もRecursionでの学習や長期インターンで理解に苦しんだ部分を中心に投稿していきたいと思います！



**参考文献**
[Java Anonymous inner class - javaTpoint](https://www.javatpoint.com/anonymous-inner-class)
[Anonymous Classes in Java - Baeldung](https://www.baeldung.com/java-anonymous-classes)
[Java Functional Interfaces - javaTpoint](https://www.javatpoint.com/java-8-functional-interfaces#:~:text=An%20Interface%20that%20contains%20exactly,Method%20Interfaces%20or%20SAM%20Interfaces.)
[Convert Anonymous Class into Lambda in Java - Baeldung](https://www.baeldung.com/java-from-anonymous-class-to-lambda)