基本的なガイドラインは、本当に例外的なものに例外を使用することです**。「普通な障がい」の場合は、Option
またはを使用することをお勧めしますEither
。誰かが間違った方法でくしゃみをしたときに例外がスローされるJavaとインターフェイスしている場合は、Try
安全を確保するために使用できます。
いくつか例を見てみましょう。
マップから何かをフェッチするメソッドがあるとします。何がうまくいかない可能性がありますか?さて、 segfault *スタックオーバーフローのような劇的で危険なもの、または要素のような期待されるものが見つかりません。segfaultスタックオーバーフローで例外をスローさせますが、単に要素が見つからない場合Option[V]
は、値または例外(またはnull
)の代わりにを返さないのはなぜですか?
ここで、ユーザーがファイル名を入力することになっているプログラムを作成しているとします。さて、何かがうまくいかなかったときにすぐにプログラムを救済するつもりがないのなら、それが進むべきEither
道です:
def main(args: Array[String]) {
val f = {
if (args.length < 1) Left("No filename given")
else {
val file = new File(args(0))
if (!file.exists) Left("File does not exist: "+args(0))
else Right(file)
}
}
// ...
}
ここで、スペースで区切られた数値を含む文字列を解析するとします。
val numbers = "1 2 3 fish 5 6" // Uh-oh
// numbers.split(" ").map(_.toInt) <- will throw exception!
val tried = numbers.split(" ").map(s => Try(s.toInt)) // Caught it!
val good = tried.collect{ case Success(n) => n }
したがって、(少なくとも)さまざまなタイプの障害に対処するための3つの方法がありOption
ます。Either
物事がうまくいくかどうか(または、実際には、相互に排他的な2つのオプションがある場合)、何がうまくいかなかったかについての情報を保存したい場合。そしてTry
、例外処理の頭痛の種全体を自分で処理したくないが、それでも例外に満足しているコードとインターフェースする必要がある場合。
ちなみに、例外は良い例になります-したがって、他の場所よりも教科書や学習教材でそれらを見つけることが多いと思います:教科書の例は非常に不完全であることが非常に多いので、通常は注意深い設計によって防止される深刻な問題が必要です代わりに、例外をスローしてフラグを立てます。
*編集:SegfaultsはJVMをクラッシュさせ、バイトコードに関係なく発生することはありません。例外でさえあなたを助けません。私はスタックオーバーフローを意味しました。
**編集:例外(スタックトレースなし)は、Scalaの制御フローにも使用されます。これらは実際には非常に効率的なメカニズムであり、ライブラリ定義のbreak
ステートメントやreturn
、制御が制御されていてもメソッドから返されるものなどを有効にします。実際に1つ以上のクロージャに渡されました。ほとんどの場合、これらの制御フローの例外の1つを誤ってキャッチする可能性があるため、すべて Throwable
をキャッチすることはそれほど優れたアイデアではないことを理解することを除いて、これについて自分で心配する必要はありません。