Effective Java 第3版を読んでいて面白いと思ったことを抜粋して書いてみる

　Effective Java 第3版を読んでいて面白いと思ったものを抜粋して書いてみます。本自体まだ読んでる途中なので、今後も追加されるかもしれません。その場合に、当記事を更新するか新しい記事を書くかは未定です。

## Item 42 : Prefer lambdas to anonymous classes
　Effective Java 第2版の「項目34 : 拡張可能なenumをインタフェースで模倣する」で紹介されていた、enumインスタンスごとに固有のメソッド実装を持たせる書き方がlambdaを使用したものに変わっていました。
　第2版での書き方はこちら。

```java:EnumFunctionV2.java
public enum EnumFunctionV2 {
    PLUS("+") {
        @Override
        public double apply(double x, double y){ return x + y; }
    },
    MINUS("-") {
        @Override
        public double apply(double x, double y){ return x - y; }
    },
    TIMES("*") {
        @Override
        public double apply(double x, double y){ return x * y; }
    },
    DEVIDE("/") {
        @Override
        public double apply(double x, double y){ return x / y; }
    };

    private final String symbol;

    // コンストラクタ
    EnumFunctionV2(String symbol) {
        this.symbol = symbol;
    }

    @Override
    public String toString() {
        return symbol;
    }

    public abstract double apply(double x, double y);
}
```

　abstractメソッドを定義して、各enumインスタンスでOverrideするやり方です。便利には便利ですが、ちょっと見辛いですね・・・。
　第3版での書き方はこちら。


```java:EnumFunctionV3.java
import java.util.function.DoubleBinaryOperator;

public enum EnumFunctionV3 {
    PLUS("+", (x, y) -> x + y),
    MINUS("-", (x, y) -> x - y),
    TIMES("*", (x, y) -> x * y),
    DEVIDE("/", (x, y) -> x / y);

    private final String symbol;
    private final DoubleBinaryOperator op;

    // コンストラクタ
    EnumFunctionV3(String symbol, DoubleBinaryOperator op) {
        this.symbol = symbol;
        this.op = op;
    }

    @Override
    public String toString() {
        return symbol;
    }

    public double apply(double x, double y) {
        return op.applyAsDouble(x, y);
    }
}
```

　abstractが消えました。コンストラクタの第2引数に[DoubleBinaryOperator](https://docs.oracle.com/javase/8/docs/api/java/util/function/DoubleBinaryOperator.html)を持たせ、そこにlambdaを使ってメソッドの実装を直接書いています。実現している内容は第2版の時と同じですが、この方がすっきりして見やすくなったように感じます。
　呼び出し方はどちらも同じです。

```ruby:EnumFunctionTest.java
public class EnumFunctionTest {
    public static void main(String... args) {
        // 第2版の方を呼び出し
        System.out.println("【v2】");
        // ループしながら全インスタンスのメソッド呼び出し
        for (EnumFunctionV2 func2: EnumFunctionV2.values()) {
            System.out.print(func2 + ":");
            System.out.println(func2.apply(1, 2));
        }
        // 各インスタンスのメソッドを個別に呼び出したい場合はこんな感じ
        System.out.println(EnumFunctionV2.PLUS.apply(1, 2));

        // 第3版の方を呼び出し
        System.out.println("【v3】");
        // ループしながら全インスタンスのメソッド呼び出し
        for (EnumFunctionV3 func3: EnumFunctionV3.values()) {
            System.out.print(func3 + ":");
            System.out.println(func3.apply(1, 2));
        }
        // 各インスタンスのメソッドを個別に呼び出したい場合はこんな感じ
        System.out.println(EnumFunctionV3.PLUS.apply(1, 2));
    }
}
```

実行結果
【v2】
+:3.0
-:-1.0
*:2.0
/:0.5
3.0
【v3】
+:3.0
-:-1.0
*:2.0
/:0.5
3.0

以上。lambdaの使い方で意外に思ったので書き留めてみました。

## おわりに
　冒頭にも書いた通り、現在(2019/5/2)、Effective Java 第3版は読んでいる途中です。しかも頭から読んでいるわけでもないので、今回(2019/5/2)Item 42について書きましたが、この後Item 1について追記する可能性もあります。第3版はItem 1～90まであります。
　Effective Javaは昔からJavaの名著として扱われているような本なので、Java使いの方は一度は読んだ方が良いと思います。第3版は、英語版は2018/1/6、日本語版は2018/10/30に発売されたものです。しばらく使えると思うので、興味ある方は是非読んでみてください。

# 参考文献
[Effective Java (3rd Edition)](https://www.amazon.co.jp/dp/0134685997)