S-JIS[2010-12-18/2013-06-08] 変更履歴

Scala try〜catch

Scalaのtry・throw式について。


throw

例外(Throwable(Exception・Error))を発生させる(投げる・スローする・throw)。

throw 例外
throw new Exception("メッセージ")

try〜catch〜finally

発生した例外をキャッチする(捕捉する・catch)。

try {
  式
  …
} catch {
  case 変数:例外クラス => 式1
  …
} finally {}

try節の中で例外が発生したら(例外が投げられたら(throwされたら))、catch節でその例外を捕捉(キャッチ)する。
例外が発生してもしなくても、finally節は実行される。

catch節の形状はmatch式と似ている。
ただし、match式が“どのcaseにもマッチしなかった”場合はMatchErrorを発生させるのに対し、
catch節でどの例外にもマッチしなかった場合はtryの外側にその例外がそのまま再スロー(伝播)される。

finally節は、例外が発生してもしなくても、最後に必ず実行される。(ただしexit()には注意

try式の値は、try節の中が正常に(例外が発生せずに)実行された場合はtry節の最後の式の値となり、例外が発生した場合はcatch節で実行されたcaseの式の値となる。
finally節の末尾の値はtry式の値とはならない。(finallyの中でreturnしたり別の例外をスローしたりできるが、すべきではないだろう)

catch節、finally節は省略できる。

Scala Java相当 備考
try {
  throw new IllegalArgumentException("aaa")
  //throw new IllegalStateException("sss")
  //throw new UnsupportedOperationException("ooo")

} catch {
  case e: IllegalArgumentException      => println("arg " + e)
  case e: IllegalStateException         => println("sta " + e)
  case e: UnsupportedOperationException => println("ope " + e)


} finally {
  println("final")
}
try {
    throw new IllegalArgumentException("aaa")
    //throw new IllegalStateException("sss")
    //throw new UnsupportedOperationException("ooo")

} catch (IllegalArgumentException e) {
    System.out.println("arg " + e)
} catch (IllegalStateException e) {
    System.out.println("sta " + e)
} catch (UnsupportedOperationException e) {
    System.out.println("ope " + e)
} finally {
    System.out.println("final")
}
 
val r = try {
  "try"
} catch {
  case e: Exception => "catch"
} finally {
  "final" //この値は戻り値にはならない
}
  tryから値を返す例。
try {
  〜
} catch {
  case _: IllegalArgumentException      => println("arg")
  case _: IllegalStateException         => println("sta")
  case _: UnsupportedOperationException => println("ope")
}
try {
    〜
} catch (IllegalArgumentException e) {
    System.out.println("arg")
} catch (IllegalStateException e) {
    System.out.println("sta")
} catch (UnsupportedOperationException e) {
    System.out.println("ope")
}
キャッチした例外を使用しない(変数として受け取る必要が無い)場合は、変数部分は「_」でよい。
try {
  〜
} catch {
  case _: IllegalArgumentException      => println("arg")
  case _: IllegalStateException         => println("sta")
  case _: UnsupportedOperationException => println("ope")
  case _ => println("other")
}
try {
    〜
} catch (IllegalArgumentException e) {
    System.out.println("arg ")
} catch (IllegalStateException e) {
    System.out.println("sta ")
} catch (UnsupportedOperationException e) {
    System.out.println("ope ")
} catch (Throwable t) {
    System.out.println("other")
}
全ての例外をキャッチしたい場合は、型の指定を無くす。
val r = try {
  〜
} catch {
  case _: IllegalArgumentException =>
    println("arg")
    "arg"
  case _: IllegalStateException =>
    println("sta")
    "state"
}
  match式と同じく、「=>」の後ろは次のcaseが来るまで1ブロックとして扱われる。
type =?>[A,B] = PartialFunction[A,B]

def pf: Throwable=?>Int = {
  case _: IllegalArgumentException      => -1
  case _: IllegalStateException         => -2
  case _: UnsupportedOperationException => -3
}
def pf2: Throwable=?>Int = {
  case _ => -99
}

try { 〜; 123 } catch pf
try { 〜; 123 } catch pf orElse pf2
  Scala2.9では、catchに(Throwableを引数に取る)部分関数を指定できるようになった。[2011-10-02]
(try式全体の戻り型は、try本体とcatchの共通の親クラスになる)
try {
  exit(0)
} finally {
  println("final")
}
try {
    System.exit(0)
} finally {
    System.out.println("final")
}
やる人はいないと思うが、
exit()関数はJavaのSystem.exit()と同じなので、
exit()を使うとfinallyは実行されない。(Javaと同様
try {
  〜
}
  Scalaでは、catchとfinallyを両方同時に省略可。
この場合のtry節に何の意味があるのかは不明^^;
try 123 finally println("final")
try 123 catch {
  case e => println(e)
} finally println("final")
  tryの本体に1つの式しか無い場合は波括弧を省略可能。[2011-02-07]
finallyも同様。
(catchは波括弧が必須)
try 123 catch {
  case t => println(t)
}
warning: This catches all Throwables. If this is really intended, use `case t : Throwable` to clear this warning.

try 123 catch {
  case t: Throwable => println(t)
}
import scala.util.control.NonFatal
try 123 catch {
  case NonFatal(t) => println(t)
}
  Scala2.10では、catchのcaseに型を何も書かないと警告が出るようになった。[2013-06-08]
→xuweiさんのScala 2.10 から try catch の catch の部分に型を書かないと警告が出るようになった件について
Throwableを明示するという方法もあるが、NonFatalを指定するのが良さそう。

throws

Scalaには、Javaのthrows句は無い。
全ての例外をメソッドの外に投げる事が出来る。

Scala Java相当 備考
def メソッド名(引数) :戻り型 = {
  〜
}
戻り型 メソッド名(引数) throws 例外クラス名 {
  〜
}
 
@throws(classOf[IllegalArgumentException])
def m():Unit = {
  throw new IllegalArgumentException()
}
@throws(classOf[IllegalArgumentException])
@throws(classOf[IllegalStateException])
def m():Unit = {
  〜
}
 
void m() throws IllegalArgumentException {
    throw new IllegalArgumentException()
}
 
void m() throws IllegalArgumentException,
                IllegalStateException {
    〜
}
明示的にどの例外が発生するかを示すにはthrowsアノテーションを使用する。

Scalaでは通常は@throwsを付ける必要は無いらしい。
JavaからScalaのメソッドを呼びたい場合に使用する。(コンパイルされたJavaコードにthrows宣言が追加される)

Scala構文へ戻る / Scala目次へ戻る / 技術メモへ戻る
メールの送信先:ひしだま