学习Scala:使用try-catch表达式处理异常
创始人
2024-04-18 18:00:39
0

Scala的异常和许多其它语言的一样。代之用普通方式那样返回一个值,方法可以通过抛出一个异常中止。方法的调用者要么可以捕获并处理这个异常,或者也可以简单地中止掉,并把异常升级到调用者的调用者。异常可以就这么升级,一层层释放调用堆栈,直到某个方法处理了它或没有剩下其它的方法。

51CTO编辑推荐:Scala编程语言专题

抛出异常

异常的抛出看上去与Java的一模一样。首先创建一个异常对象然后用throw关键字抛出:

  1. throw new IllegalArgumentException 

尽管可能感觉有些出乎意料,Scala里, throw也是有结果类型的表达式。下面举一个有关结果类型的例子:

  1. val half =  
  2.   if (n % 2 == 0)  
  3.     n / 2 
  4.   else 
  5.     throw new RuntimeException("n must be even")  

这里发生的事情是,如果n是偶数,half将被初始化为n的一半。如果n不是偶数,那么在half能被初始化为任何值之前异常将被抛出。因此,无论怎么说,把抛出的异常当作任何类型的值都是安全的。任何使用从throw返回值的尝试都不会起作用,因此这样做无害。

从技术角度上来说,抛出异常的类型是Nothing。尽管throw不实际得出任何值,你还是可以把它当作表达式。这种小技巧或许看上去很怪异,但像在上面这样的例子里却常常很有用。if的一个分支计算值,另一个抛出异常并得出Nothing。整个if表达式的类型就是那个实际计算值的分支的类型。Nothing类型将在以后的11.3节中讨论。

捕获异常

用来捕获异常的语法展示在代码7.11中。选择catch子句这样的语法的原因是为了与Scala很重要的部分:模式匹配:pattern matching保持一致。模式匹配是一种很强大的特征,将在本章概述并在第十五章详述。

  1. import java.io.FileReader  
  2. import java.io.FileNotFoundException  
  3. import java.io.IOException  
  4. try {  
  5.  val f = new FileReader("input.txt")  
  6.  // Use and close file  
  7. } catch {  
  8.  case ex: FileNotFoundException => // Handle missing file  
  9.  case ex: IOException => // Handle other I/O error  
  10. }  

代码 7.11 Scala的try-catch子句

这个try-catch表达式的行为与其它语言中的异常处理一致。程序体被执行,如果抛出异常,每个catch子句依次被尝试。本例中,如果异常是FileNotFoundException,那么第一个子句将被执行。如果是IOException类型,第二个子句将被执行。如果都不是,那么try-catch将终结并把异常上升出去。

注意

你将很快发现与Java的一个差别是Scala里不需要你捕获检查异常:checked exception,或把它们声明在throws子句中。如果你愿意,可以用ATthrows标注声明一个throws子句,但这不是必需的。

finally子句

如果想让某些代码无论方法如何中止都要执行的话,可以把表达式放在finally子句里。如,你或许想让打开的文件即使是方法抛出异常退出也要确保被关闭。代码7.12展示了这个例子。

  1. import java.io.FileReader  
  2. val file = openFile()  
  3. try {  
  4.  // 使用文件  
  5. } finally {  
  6.  file.close() // 确保关闭文件  
  7. }  

代码 7.12 Scala的try-finally子句

注意

代码7.12展示了确保非内存资源,如文件,套接字,或数据库链接被关闭的惯例方式。首先你获得了资源。然后你开始一个try代码块使用资源。最后,你在finally代码块中关闭资源。这种Scala里的惯例与在Java里的一样,然而,Scala里你还使用另一种被称为贷出模式:loan pattern的技巧更简洁地达到同样的目的。

生成值

和其它大多数Scala控制结构一样,try-catch-finally也产生值。如,代码7.13展示了如何尝试拆分URL,但如果URL格式错误就使用缺省值。结果是,如果没有异常抛出,则对应于try子句;如果抛出异常并被捕获,则对应于相应的catch子句。如果异常被抛出但没被捕获,表达式就没有返回值。由finally子句计算得到的值,如果有的话,被抛弃。通常finally子句做一些清理类型的工作如关闭文件;他们不应该改变在主函数体或try的catch子句中计算的值。

  1. import java.net.URL  
  2. import java.net.MalformedURLException  
  3. def urlFor(path: String) =  
  4.  try {  
  5.   new URL(path)  
  6.  } catch {  
  7.   case e: MalformedURLException =>  
  8.    new URL("http://www.scalalang.org")  
  9.  }  

代码 7.13 能够产生值的catch子句

如果熟悉Java,不说你也知道,Scala的行为与Java的差别仅源于Java的try-finally不产生值。Java里,如果finally子句包含一个显式返回语句,或抛出一个异常,这个返回值或异常将“凌驾”于任何之前源于try代码块或某个它的catch子句产生的值或异常之上。如:

  1. def f(): Int = try { return 1 } finally { return 2 }  

调用f()产生结果值2。相反:

  1. def g(): Int = try { 1 } finally { 2 }  

调用g()产生1。这两个例子展示了有可能另大多数程序员感到惊奇的行为,因此通常最好还是避免从finally子句中返回值。最好是把finally子句当作确保某些副作用,如关闭打开的文件,发生的途径。

【相关阅读】

  1. Scala中的for表达式:枚举的“瑞士军刀”
  2. Scala中的if表达式和while循环
  3. 学习Scala的重载方法和隐式转换
  4. Scala的四种标识符构成方式
  5. Scala的私有字段和定义操作符

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...