Quantcast
Channel: 例外タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 100

Scalaのscala.util.TryでJavaのtry-catch-finallyを表現する

$
0
0

Javaのtry-catch-finallyは致命的なエラー(FatalError)は捕捉しませんが、
Scalaのtry-catch-finallyは致命的なエラーも捕捉してしまいます。
致命的な例外として有名なのはOutOfMemoryErrorなどがあり、このような致命的な例外はプログラム中で捕捉すべきではありません。

scala> try {
     |   throw new StackOverflowError
     | } catch {
     |   case e: Throwable => println("error")
     | }
error

そこで、Scalaではtry-catch-finallyではなく、scala.util.Tryを使って例外を捕捉する方法が一般的(?)になっています。
scala.util.Tryは、Javaのtry-catch-finallyと同様に致命的ではないエラー(NonFatalError)しかキャッチしません。

scala> Try(throw new StackOverflowError) recover {
     |   case e: Throwable => println("error")
     | }
java.lang.StackOverflowError
  at .$anonfun$res13$1(<console>:13)
  at scala.util.Try$.apply(Try.scala:209)
  ... 38 elided

でも、scala.util.Tryは、例外がスローされた時にはFailureになってしまい、最後に何かを実行するfinallyのような仕組みはありません。 Scalaでもfinallyしたい。そんな時があると思います。

そんな時にはscala.util.control.Exception.ultimatelyを使うという手段があります。例外が発生してもしなくても最後に実行する処理を渡すことでfinallyを実現可能です。

scala> Try {
     |   ultimately {
     |     println("finally !")
     |   } {
     |     println("do something")
     |     throw new Exception
     |     println("no execute")
     |   }
     | }
do something
finally !
res: scala.util.Try[Unit] = Failure(java.lang.Exception)

このような書き方であれば、致命的なエラーに関しては無視し、致命的ではないエラーのみを補足することができます。
もちろんfinallyを使う必要がないならultimatelyも必要ありません。

参考文献

scala.util.control.Exceptionに関する日本語の記事は2つぐらいしかないです。

追記

コメントいただきましたが、Scalaのtry-catch-finallyでも、
catchNonFatalを用いてパターンマッチを行うと、致命的ではないものだけを補足できます。

NonFatalの例外 - scala_text


Viewing all articles
Browse latest Browse all 100

Trending Articles