流れるようなインターフェースで例外処理

例外処理を書くのがいつも面倒なので少しアレンジしてみました。

```java:チェック例外を発生させるメソッド
void raiseIOEx1(String s) throws IOException {
    if (s.equals("nagare")) {
        System.out.println("Excellent!");
        return;
    }
    throw new IOException("invalid input :".concat(s));
}
```
雑ですが上記のようなメソッドがあるとき(なんでIOExceptionなん？とかは置いておいて)

```java:普通の書き方
void usually_try_style() {
    try {
        raiseIOEx1("nagare");
    } catch (IOException e) {
        e.printStackTrace();
    }
}
```

```java:アレンジした書き方
void nagare_try_style() {
    Try.throwable(this::raiseIOEx1)
            .ifCatch(IOException::printStackTrace)
            .accept("nagare");
}
```
こんな感じで書けます。

また、値を返すメソッドの場合も以下のように書けます。

```java:チェック例外を発生させるメソッド2
String raiseIOEx2(String s) throws IOException {
    if (s.equals("nagare")) {
        return "Excellent!";
    }
    throw new IOException("invalid input :".concat(s));
}
```
```java:普通の書き方
void usually_returnable_try_style() {
    try {
        String s = raiseIOEx2("nagare");
        System.out.println(s);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
```

```java:アレンジした書き方
void nagare_returnable_try_style() {
    Optional<String> s = Try.throwable(this::raiseIOEx2)
            .ifCatch(IOException::printStackTrace)
            .apply("nagare");
    s.ifPresent(System.out::println);

    // or
    Try.throwable(this::raiseIOEx2)
            .ifCatch(IOException::printStackTrace)
            .apply("nagare");
            .ifPresent(System.out::println);
}
```

業務レベルで使用するのはおすすめできませんが、以下の4クラスを追加することで上記のような記述が可能になります。

```java
public class Try {
    public static <X, A, E extends Exception> ThrowableFunc<X, A, E> throwable(
            ThrowableFunc<X, A, E> f) {
        return f;
    }

    public static <X, E extends Exception> ThrowableSpender<X, E> throwable(
            ThrowableSpender<X, E> s) {
        return s;
    }
}

@FunctionalInterface
public interface ThrowableSpender<X, E extends Exception> {
    void accept(X x) throws E;

    default Consumer<X> ifCatch(ExHandler<E> handler) {
        return (X x) -> {
            try {
                accept(x);
            } catch (Exception e) {
                @SuppressWarnings("unchecked")
                E typedE = (E) e; // is type safe
                handler.handle(typedE);
            }
        };
    }
}

@FunctionalInterface
public interface ThrowableFunc<X, A, E extends Exception> {
    A apply(X x) throws E;

    default Function<X, Optional<A>> ifCatch(ExHandler<E> handler) {
        return x -> {
            try {
                return Optional.of(apply(x));
            } catch (Exception e) {
                @SuppressWarnings("unchecked")
                E typedE = (E) e; // is type safe
                handler.handle(typedE);
            }
            return Optional.empty();
        };
    }
}

@FunctionalInterface
public interface ExHandler<E extends Exception> {
    void handle(E e);
}
```

コード読んでいただけると分かると思いますが`catch`のところで少しズルをしています。

```java
try {
    accept(x);
} catch (E e) {
    handler.handle(e);
}
```
みたいな感じで書けるようになれば複数例外を捕まえるのもインターフェースだけで記述できるようになり色々捗りそうなんですが、残念です。java9では書けるようになるといいですね。

https://github.com/mt-village/nagare

# 参考
- [Java8のStreamやOptionalでクールに例外を処理する方法](http://qiita.com/q-ikawa/items/3f55089e9081e1a854bc)