异常捕获
scala 和 Java 类似,也有try & catch 语义来捕获异常。scala 的异常捕获如下:
object TestFuture {
def main(args: Array[String]): Unit = {
var num = 1
try {
num = 100/0 // 生成算数异常
} catch {
// :type 表示是否匹配 type 类型
case e: ArithmeticException => println(e.getMessage)
case e: RuntimeException => println(e.getMessage)
// ... 其他方式一并用 case 处理
} finally {
// .. 不论是否处理异常,都会执行这个代码块
println("run finally")
}
}
}
catch块中,我们使用case来匹配可能出现的异常情况,上述代码的输出为:
/ by zero
run finally
try .. catch 方式虽然能捕获,但是实现方式不优雅,如果是在 rpc 等异步环境下,代码结构会非常混乱。因此,我们更推荐使用下面的Try 方式处理。
Try 方式
给出Try 的最基本使用方式:
import scala.util.{Failure, Success, Try}
object TestFuture {
def main(args: Array[String]): Unit = {
divide(1, 2) match {
case Success(num) => println(num)
case Failure(e) => println(e.getMessage)
}
divide(1, 0) match {
case Success(num) => println(num)
case Failure(e) => println(e.getMessage)
}
}
def divide(a: Int, b: Int): Try[Int] = {
b match {
case 0 => Failure(new ArithmeticException(s"$a divide by zero"))
case _ => Success(a / b)
}
}
}
输出结果:
0
1 divide by zero
我们可以看出match方式,如果成功则返回Success[T] 的类型,否则返回Failure包装的Exception
如果我们想要在失败时候获取默认值,可以使用getOrElse 的方式。举个例子:
import scala.util.{Failure, Success, Try}
object TestFuture {
def main(args: Array[String]): Unit = {
val result1= divide(6, 2) getOrElse -1
val result2 = divide(6, 0) getOrElse -1
println(s"result1 = $result1, result2 = $result2")
}
def divide(a: Int, b: Int): Try[Int] = {
b match {
case 0 => Failure(new ArithmeticException(s"$a divide by zero"))
case _ => Success(a / b)
}
}
}
此时输出结果:
result1 = 3, result2 = -1
假设我们想单独处理一些特殊的异常,剩下的按照默认值处理,则可以使用recover 的方式,代码示例:
import scala.util.{Failure, Success, Try}
object TestFuture {
def main(args: Array[String]): Unit = {
val result = divide(1, 2) recover {
case e: ArithmeticException => println(e.getMessage)
case e: RuntimeException => println(e.getMessage)
case _ => "recover failed"
}
println(result.get)
}
def divide(a: Int, b: Int): Try[Int] = {
b match {
case 0 => Failure(new ArithmeticException(s"$a divide by zero"))
case -1 => Failure(new RuntimeException("runtime failed"))
case _ => Success(a / b)
}
}
}
注意,如果没有异常,则返回Success[T],只有失败的时候才会走Recover 的逻辑