我需要初始化一组val,初始化它们的代码可能会引发异常.我想写:
try {
val x = ... generate x value ...
val y = ... generate y value ...
} catch { ... exception handling ... }
... use x and y ...
Run Code Online (Sandbox Code Playgroud)
但是这(显然)不起作用,因为x和y不在try之外的范围内.
通过使用可变变量很容易解决问题:
var x: Whatever = _
var y: Whatever = _
try {
x = ... generate x value ...
y = ... generate y value ...
} catch { ... exception handling ... }
... use x and y ...
Run Code Online (Sandbox Code Playgroud)
但那并不是很好.
通过复制异常处理也很容易解决问题:
val x = try { ... generate x value ... } catch { ... exception handling ... }
val y = try { ... generate y value ... } catch { ... exception handling ... }
... use x and y ...
Run Code Online (Sandbox Code Playgroud)
但这涉及重复异常处理.
必须有一个"好"的方式,但它是在逃避我.
模式匹配怎么样?
val (x, y) = try generateX -> generateY catch { /*exception handling*/ }
Run Code Online (Sandbox Code Playgroud)
要么
val (x, y) = try (generateX, generateY) catch { /*exception handling*/ }
Run Code Online (Sandbox Code Playgroud)
agilesteel的答案很好,如果你只想捕获任何抛出的异常并在catch块中执行某些程序.但是,您可能希望稍后单独处理异常,在这种情况下,您可能会考虑将类型设置为Option或Either.
执行此操作的内置方法是使用Catch对象.请参阅例外文档.
您如何使用它取决于发生异常时您想要发生的事情.例如
import util.control.Exception.allCatch
def handleInfinities(n: Int) = {
val x = allCatch.either { 100 / n } // Either[Throwable, Int]
val y = allCatch.either { 100 / (n - 1) }
Seq(x, y) map { case Left(_) => Int.MaxValue; case Right(z) => z }
}
Run Code Online (Sandbox Code Playgroud)
然后handleInfinities(1)给出
Seq[Int] = List(100, 2147483647)
Run Code Online (Sandbox Code Playgroud)
注意变量赋值和异常处理现在是如何完全分开的.
一个简单的解决方案是定义一个使用by-name参数的包装函数.
def safely[T](f: => T): T = try { f } catch { /* exception handling */ }
// You'll have to play around with safely's type signature, depending on what
// you do in the exception handling
val x = safely { generateX }
val y = safely { generateY }
Run Code Online (Sandbox Code Playgroud)
或者,如果你感觉真的很时髦,Scala 2.9允许将部分函数用作异常处理程序.
val handler: PartialFunction[Throwable, Unit] = { /* exception handling */ }
val x = try { generateX } catch handler
val y = try { generateY } catch handler
Run Code Online (Sandbox Code Playgroud)
总的来说,我会说第一种方法是最直接的.但是如果你可以编写可以使用orElseor 组合在一起的可重用的异常处理程序andThen,那么第二种方法会更合适.