web-dev-qa-db-ja.com

ScalaのNonFatalとExceptionの違い

この記事 では、次のように書かれています:

通常発生する「すべて」をキャッチする場合は、NonFatalを使用します。

import scala.util.control.NonFatal

try {
  operation()
} catch {
  case NonFatal(e) => errorHandler(e)
}

ただし、通常はExceptionを使用します。

try {
  operation()
} catch {
  case e: Exception => errorHandler(e)
}

ScalaのNonFatalExceptionの違いは何ですか? Exception in Scalaは致命的な例外を含みますか?

Javaの場合、Exceptionは致命的ではないエラー用、Errorは致命的エラー用です。 scala= Exceptionに関してJavaと異なりますか?

致命的でない例外をキャッチする正しい方法はどれですか?

32
null

編集:最新のScalaバージョン(2.11+ではNonFatal.applyの定義が異なります)に更新されました。


NonFatalは、scala.util.controlで定義されている便利な抽出ツールです。

object NonFatal {
   /**
    * Returns true if the provided `Throwable` is to be considered non-fatal, or false if it is to be considered fatal
    */
   def apply(t: Throwable): Boolean = t match {
     // VirtualMachineError includes OutOfMemoryError and other fatal errors
     case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable => false
     case _ => true
   }
  /**
   * Returns Some(t) if NonFatal(t) == true, otherwise None
   */
  def unapply(t: Throwable): Option[Throwable] = if (apply(t)) Some(t) else None
}

JVMには特別な「致命的な」種類の例外はありません-Errorsは常に「致命的な」ものではなく、単に特別な種類の内部例外です。 「致命的な」例外は、NonFatal定義で使用される例外の単なるリストです。この用語では、Exceptionを除くすべてのInterruptedExceptionsは致命的ではないと見なされます。 InterruptedExceptionが致命的であると考えるのは理にかなっています。スレッドが中断されることを意味するため、それを処理する場合は明示的に行う必要があります。

NonFatalエクストラクターもControlThrowablesを正しく処理します。これらは、break内のbreakableのような特別な制御伝達関数によってスローされる例外です。

35

Scalaでは例外についてはあまり言及されていませんが、それでも予期しない障害に対処する際に複数回行われることです。

Java.lang.Errorをキャッチするとき?複数の回答があり、意見がありますが、焦点を合わせましょう共通部分に。

合理的なアプリケーションはキャッチしようとしないでください

  • 「エラーはThrowableのサブクラスであり、合理的なアプリケーションがキャッチしようとしてはならない重大な問題を示します。」
  • 「Java仮想マシンが壊れているか、動作を継続するために必要なリソースが不足していることを示すためにスローされます。」
  • 「Java仮想マシンはオブジェクトがメモリ不足であり、ガベージコレクタがそれ以上メモリを使用できないため、オブジェクトを割り当てることができない場合にスローされます。」

NonFatalは、致命的ではないThrowableのExtractorです。 VirtualMachineError(たとえば、OutOfMemoryErrorおよびStackOverflowErrorVirtualMachineErrorのサブクラス)、ThreadDeathLinkageErrorInterruptedExceptionControlThrowable、これらは、妥当なアプリケーションがキャッチしようとしてはならない障害の一部です。

これを念頭に置いて、すべての無害なThrowablesをキャッチするコードを作成できます。

try {
  // dangerous code
} catch {
  case NonFatal(e) => log.error(e, "Something not that bad.")
}

Applyメソッドを見ると、非常にはっきりとわかります。

object NonFatal {
   /**
    * Returns true if the provided `Throwable` is to be considered non-fatal, or false if it is to be considered fatal
    */
   def apply(t: Throwable): Boolean = t match {
     // VirtualMachineError includes OutOfMemoryError and other fatal errors
     case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable => false
     case _ => true
   }
}
2
OBarros