假设我正在使用我的 Scala 项目中的 Java 库。该 Java 库会到处抛出异常,但让它们“在 Scala 世界中”传播我感到不舒服,因为无法确定 Scala 方法可以抛出哪些异常(除非通过记录它们)。所以这是我倾向于编写的代码:
def doesNotThrowExceptions(parameter: String): Either[Throwable, T] =
catching(classOf[IOException], classOf[NoSuchAlgorithmException]) either {
// Code calling the Java library
// Code generating a value of type T
}
然后,通常,我会使用
Either.RightProjection.flatMap
链接返回 Either[Throwable, ...]
的方法或 Either.RightProjection.map
混合返回 Either[Throwable, ...]
的方法和其他方法。或者干脆 Either.fold
用 Throwable
做点什么值(value)。然而,不知何故,这仍然感觉不完全正确。这是在 Scala 中处理 Java 异常的最“惯用”方式吗?没有更好的办法吗?
最佳答案
我不确定是否有一种最惯用的方法来处理 Java 的异常,因为它们至少会抛出四种不同的情况:
对于这些案例中的每一个,最佳实践可以说是不同的
1. 真正的异常(exception)
Scala 具有功能齐全的异常处理。让意外的异常传播未被发现并没有错,直到您达到可以对此做些什么的水平。将所有可能的异常打包成
Either
会浪费很多时间。只需记录您知道您没有处理的内容,并在适当的高级别使用 try/catch(例如 saveEverything
方法可能应该放在 try/catch 块中(或将其内容包装在一个块中),因为无论发生了什么错误,如果保存所有内容失败,您可能想尝试挽救这种情况,而不仅仅是死亡)。特别是,您可能想要处理
Error
以这种方式只打包 Exception
,并非所有 Throwable
s,进入Either
.2. 您需要了解的异常(exception)情况
这就是你所说的情况,你已经就如何处理这些问题给出了一些很好的建议。正如您已经注意到的,您可以使用
catching
将异常打包成 Either
.然后你也可以一种。使用模式匹配,这会让你分开你的
Either
更深入:doesNotThrowExceptions("par").right.map(transformData) match {
case Left(ioe: IOException) => /* ... */
case Left(nsae: NoSuchAlgorithmException) => /* ... */
case Right(x) => /* ... */
case Left(e) => throw e // Didn't expect this one...
}
湾下变频到
Option
记录错误后:doesNotThrowExceptions("par").left.map{ e =>
println("You're not going to like this, but something bad happened:")
println(e)
println("Let's see if we can still make this work....")
}.right.toOption
C。如果异常是您的流程控制的一个非常重要的部分,
Either
可能还不够。您可能想要定义自己的 Either
- 类似类(class),不仅仅是 Left
和 Right
.或者您可以嵌套 Either
的左侧:try { Right(/* java code */) }
catch {
case ioe: IOException => Left(Left(ioe))
case nsae: NoSuchAlgorithmException => Left(Right(nsae))
}
d.使用 Scalaz
Validation
,这很像 Either
但针对异常处理进行了更多定制。3. 您只需要知道出现问题的异常(exception)情况,以及
4. 抛出异常表示无返回值
尽管它们在概念上是两个不同的类别,但您可以以相同的方式处理它们:
catching(classOf[IOException], classOf[NoSuchAlgorithmException]) opt { ... }
获得
Option
背部。然后map
, flatMap
, 等等..
关于Scala:处理来自 Java 库的异常的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9291600/