Scala優雅な異常処理のtryとTry


Scala優雅な異常処理のtryとTry
JAvaはすべてのエラーをThrowableにカプセル化し、Throwableの下にはErrorとExceptionの2つのサブクラスがあります.scalaは本質的にjavaと同様にjvm上で動作し、同じscalaにもjavaと同様のtry catch異常処理メカニズムがあり、scalaには多くの文法糖があり、異常処理の過程で開発者の大きな精力を節約することができる.以下、scala異常処理tryとTryの使用を見てみる.
 
try
基本的な書き方
tryはscala内で異常処理として使われる書き方で、最もよく使われる書き方はtry catch finallyです
  def tryDemo(): Unit = {
    // try
    val label = try {
      val value = redis.get("key")
      if (noRes.contains(value)) {
        "-1"
      } else {
        "1"
      }
    } catch {
      case e: Exception => {
        e.printStackTrace()
        "-1"
      }
    } finally {
      println("label    ")
    }
    println(label)
  }

Exception
ここでcatchからexceptionは例外処理を行い、デフォルト値-1を返します.Exceptionはjava.lang.Exceptionです.catch Exceptionは次のようなException異常を捉えますが、errorが捉えられない場合:
java.lang.RuntimeException
システム異常
java.lang.NullPointerException
空ポインタ異常
java.lang.ClassCastException
タイプ変換例外
java.lang.IndexOutOfBoundsException
下付き境界線
java.lang.ArrayIndexOutOfBoundsException
配列の下付き境界
java.lang.StringIndexOutOfBoundsException
文字列の下限
java.lang.UnsupportedOperationException
サポートされていない操作異常
java.lang.IllegalArgumentException
不正なパラメータ異常
java.lang.NoSuchElementException
方位に異常は見つかりません
java.lang.NumberFormatException
数値フォーマット異常
java.lang.AbstractMethodError
抽象メソッドエラー
java.lang.InterruptedException
割り込み例外
Error
Errorはjava.lang.Errorです.Exceptionクラス以外の異常をキャプチャする必要がある場合は、次のように書き換えるだけです.
      case e: Error => {
        xxx
      }

一般的にネットワークに接続してサーバーの初期化に失敗した場合、errorが発生しますが、一般的にバグを書く場合はExceptionが多いです
Scala構文糖
scalaサポート_すべてを表す、一般的なmap(.toString)、foreach(println())など、ここでtry catchはこのような書き方をサポートします.
      case _ => {
        xxx
      }

catch後にこれを加えると、すべての異常をキャプチャすると見なすことができます.error、exceptionには、サボっている場合や異常の状況がよく分からない場合が含まれていますが、コードの可読性が悪く、mavenパッケージ時にパッケージのwarningを注意します.
 
Try
TryのメカニズムはoptionとFutureに似ていますが、最終的に値を取得する必要がある場合は、実行が不確実性であるため、.getで取得する必要があります.
基本的な書き方
    val numStr = "0"
    val num = Try(numStr.toInt).get
    println(num,num.getClass)
(0,int)

ソースコード
object Try {
  /** Constructs a `Try` using the by-name parameter.  This
   * method will ensure any non-fatal exception is caught and a
   * `Failure` object is returned.
   */
  def apply[T](r: => T): Try[T] =
    try Success(r) catch {
      case NonFatal(e) => Failure(e)
    }

}

r 私たちが実行している操作です 実行後に返される結果であり、上記の例に対して、r toInt,Tです Intです.ここではTryの下位層もtryを使用していることがわかります.SuccessはTry内のcase classであり、Tryのサブクラスでもあります.クラス内にはisSuccess、isFailureなどの方法が提供されています.その戻り値もTry[T]です.eはtryを実行するときに投げ出される異常です.次のソースコードから見るとThrowableで、ErrorとExceptionが含まれています.異常をキャプチャするとFailureに戻ります.FailureはSuccessと同じくTryのサブクラスです.
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
}

パターンマッチング判定Try内でmatchが正常に実行されたか
      import scala.util.{Failure, Success, Try}      
      Try(num.toInt) match {
        case Success(value) => println("Success")
        case Failure(exception) => println("False")
        case _ => println("unKnown")
      }

match caseモードマッチングおよびscalaに付属のSuccessクラスとFailureクラスにより、Try内のロジックが正常に実行されているかどうかを判断し、正常にSuccessに戻り、エラーを実行してFailureに戻ることができます.ここで.toIntは最もよく使われる書き方で、複雑なロジックを書くこともできます.例えば、ネットワークリクエストのタスクやファイルIOなどが必要です.
リカバリモードマッチングと異常処理recover
    Try(num.toInt) recover {
      case e: Exception => 0
      case e: Error => 1
      case _ => 2
    }

ここでtry catch flinalyとは、どちらの書き方でも、異常捕捉と修復が可能であり、Try内に異常が投げ出された場合、異常処理により異常が発生した後の処理動作を判断し、実行結果状態がSuccessであれば後続のrecoverはトリガーされない.
簡潔な書き方
上記のcase matchとrecoverに対して、Tryは開発者が使用するためのより簡単な書き方、すなわちgetOrElseを提供し、Try内が成功した場合、Tを返し、そうでなければmapとjsonObjectのgetOrElseのようなデフォルト値を返す.
A.try catch
    try {
      num.toInt
    } catch {
      case e: Exception => 0
    } 

B.if else
      if (num != null && num != "") {
        num.toInt
      } else {
        0
      }

C.Try
Try(num.toInt).getOrElse(0)