S-JIS[2010-12-18/2013-06-08] 変更履歴
Scalaのtry・throw式について。
|
|
|
例外(Throwable(Exception・Error))を発生させる(投げる・スローする・throw)。
throw 例外
throw new Exception("メッセージ")
発生した例外をキャッチする(捕捉する・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を指定するのが良さそう。 |
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宣言が追加される) |