我在学习Scala,对try-catch-finally
语法感到困惑。
在Scala语法规范中,它说:
Expr1 ::= ‘try’ Expr [‘catch’ Expr] [‘finally’ Expr]
| ...
我可以在没有{
}
块的情况下写这样的表达式吗:
try
println("Hello")
catch
RuntimeException e => println("" + e)
finally
println("World")
或者表达式必须是块表达式?
Scala 3(Dotty(正在尝试使用可选的大括号(显著缩进(,因此以下方法适用于
scala> try
| 1 / 0
| catch
| case e => println(s"good catch $e")
| finally
| println("Celebration dance :)")
|
good catch java.lang.ArithmeticException: / by zero
Celebration dance :)
val res1: AnyVal = ()
我们注意到处理程序
case e => println(s"good catch $e")
不像Scala 2中那样需要大括号。事实上,由于catch
关键字后的case
子句的特殊处理,以下内容也适用于
scala> try
| 1 / 0
| catch
| case e => println(s"good catch $e")
| finally
| println("Celebration dance :)")
|
good catch java.lang.ArithmeticException: / by zero
Celebration dance :)
val res2: AnyVal = ()
其中我们注意到处理程序不必在catch
之后缩进
catch
case e => println(s"good catch $e")
当然。
import scala.util.control.NonFatal
def fourtyseven: PartialFunction[Throwable, Int] = {
case NonFatal(_) => 47
}
def attempt(n: => Int): Int =
try n catch fourtyseven finally println("done")
println(attempt(42))
println(attempt(sys.error("welp")))
尽管我必须单独定义catch
表达式(因为它需要大括号(,但它可以按预期编译和运行。
你可以在Scastie上玩这个代码。
注意事项:
try
/catch
/finally
是一个返回值的表达式(如果您来自Java,这可能有点不熟悉(--您可以在文档中阅读更多关于它的信息catch
总是从Throwable
取一个PartialFunction
到某个类型,try
/catch
的整体返回类型是两者中最接近的公共超类(例如,假设您有class Animal; class Dog extends Animal; class Cat extends Animal
,如果try
返回Dog
,catch
返回Cat
,则整个表达式将返回Animal
(- 我在
catch
部分函数中使用了NonFatal
提取器,您可以在这个答案中阅读更多关于它的信息,而提取器对象通常在官方文档中进行了描述