5
2

More than 1 year has passed since last update.

Java 例外を投げ直せ

Last updated at Posted at 2021-12-22

Javaのカレンダー | Advent Calendar 2021の14日目の記事です

※ 北斗の拳のようなタイトルになってしまって申し訳ありません

概要

@SneakyThrows を使って検査例外(チェック例外)を非検査例外(非チェック例外)?に投げ直すやり方
Stream API では、検査例外は try - catch で握る必要があるので、非検査例外にすることでコードをシンプルに保ちます

参考

やり方

before

    void tryCatch() {
        Stream.of("2021/12/22", "2021/12/23", "a").map(s -> {
            try {
                return new SimpleDateFormat("yyyy/MM/dd").parse(s);
            } catch (ParseException e) {
                return new RuntimeException(e);
            }
        }).forEach(System.out::println);
    }

after

    void sneakyThrows() {
        Stream.of("2021/12/22", "2021/12/23", "a").map(this::parse).forEach(System.out::println);
    }

    @SneakyThrows
    Date parse(String s) {
        return new SimpleDateFormat("yyyy/MM/dd").parse(s);
    }

説明

Stream API の中間操作で検査例外が発生する場合は、try - catch で例外を受け付ける必要があるため、冗長な例外処理を書く必要があります。
これに対応するため、検査例外を投げる処理を別のメソッドに抽出して、@SneakyThrows アノテーションをつけることで検査例外の例外処理のコードを省略するテクニックです。

ポイント

  • 別メソッドに抽出しているため、コードの行数は変わらない。もしくは増える場合がある。が、可読性は増す。
  • 必要に応じて、呼び出しの大元で適切な例外処理を書くことは当然必要。スタックトレースを出せば、どこで発生したかはわかるため不安はない。
    • SpringBoot であれば @RestControllerAdvice がオススメ
  • 中間操作で例外を握りつぶす(イレギュラーな状態でも処理を継続したい)必要がある場合は、 try - catch を利用して例外処理を書きます
  • @SneakyThrows は、検査例外を非検査例外に詰め直しているわけではない(javac 時に一時的に検査例外として認識されないようにしている)ので、投げられる例外は、検査例外になっている(そして、UndeclaredThrowableExceptionになってしまう?ちょっと自信なし)
  • 別メソッドに切り出す必要もないほどのコード(例のコードもそうではあるが) jOOQ の Unchecked.throwChecked() を検討してもよい
5
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2