博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
内建控制结构之使用try表达式处理异常
阅读量:6078 次
发布时间:2019-06-20

本文共 3589 字,大约阅读时间需要 11 分钟。

  hot3.png

抛出异常

异常的抛出看上去与Java一模一样,首先创建一个异常对象然后用throw关键字抛出。但在scala里,throw也是有结果类型的表达式。下面举个有关结果类型的例子:

package scalaTestobject Test6 {    def main(args:Array[String]):Unit = {        println(fun(9))    }    def fun(n:Int) = {        if(n % 2 == 0) n/2        else throw new RuntimeException("n must be even")    }}

执行结果:

133853_u3eh_168814.jpg

这段代码的意思是,如果n是偶数,将打印n的一半。如果n不是偶数,那么异常将被抛出。因此,无论怎么说,把抛出的异常当作任何类型的值都是安全的。任何使用经throw返回值的尝试都不会起作用,因此这样做不会有害处

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

捕获异常

package scalaTestimport java.io.FileReaderimport java.io.FileNotFoundExceptionimport java.io.IOExceptionobject Test6 {    def main(args:Array[String]):Unit = {        try {            val f = new FileReader("input.txt")            //使用并关闭文件,省略....................        }catch{            case ex:FileNotFoundException => {                println("文件没有找到!")            }            case ex:IOException => println("IO异常")        }    }}

上面演示了捕获异常的语法。选择catch子句这种语法的原因是为了与scala很重要的部分:模式匹配保持一致,模式匹配是一种很强大的特征(我们在后面章节中会讲到)。

这个try-catch表达式的处理方式与其他语言中的异常处理一致。首先执行程序体,如果抛出异常,则依次尝试每个catch子句。本例中,如果异常是FileNotFoundException,那么第一个子句将被执行。如果是IOException类型,第二个子句将被执行。如果都不是,那么try-catch将终结把异常向上抛出去。
注意
你将很快发现与java的差别是scala里不需要捕获检查异常,或把它们声明在throws子句中。如果愿意,你可以用@throws注解声明throws子句,但这不是必须的(这个后面会讲到)。

finally子句

如果想让某些代码无论方法如何中止都要执行的话,可以把表达式放在finally子句里。如例:

package scalaTestimport java.io.FileReaderimport java.io.FileNotFoundExceptionimport java.io.IOExceptionobject Test6{    def main(args:Array[String]):Unit = {        try{           val f = new FileReader("input.txt")            //省略.......        }catch{            case ex:FileNotFoundException => {                println("文件没有找到")            }            case ex:IOException => println("IO异常")        }finally{            println("必须执行的语句")        }    }}

或者

package scalaTestimport java.io.FileReaderimport java.io.FileNotFoundExceptionimport java.io.IOExceptionobject Test6{    def main(args:Array[String]):Unit = {        try{            val f = new FileReader("./.classpath")            println(f.getEncoding())            //省略...........        }finally{            println("必须执行的语句")        }    }}

注意:一般确保内存资源,如:文件套接字数据库连接等被关闭的惯例方式在finally中进行处理,这跟在java中是一样的。Scala里还可以使用另一种被称为出借模式(loan pattern)的技巧更简洁地达到同样的目的(这个出借模式后面再讲)。

生成值

和其他大多数scala控制结构一样,try-catch-finally也产生值。如例:

package scalaTestimport java.net.URLimport java.net.MalformedURLExceptionobject Test6 {    def main(args:Array[String]):Unit = {        println(urlFor("ddd"))    }    def urlFor(path:String) = {        try{            new URL(path)        }catch{            case e:MalformedURLException => new URL("http://www.scala-lang.org")        }    }}

结果:

144851_oReT_168814.jpg

上例演示了如何尝试拆分URL,但如果URL格式错误就使用默认值。也就是,如果没有异常抛出,则对应于try子句;如果抛出异常并被捕获,则对应于相应的catch子句。如果异常被抛出但没被捕获,表达式就没有返回值

由finally子句计算得到的值,即使有也会被抛弃通常finally子句做一些诸如关闭文件之类的清理工作,它们不应该修改主函数体或catch子句中计算的值。
Scala的行为与java的差别仅在于java的try-finally不产生值。在java里,如果finally子句包含返回语句,或抛出一个异常,这个返回值或异常将“凌驾”于任何之前在try代码块或某个catch子句里产生的值或异常之上。
我们来测试一下,scala的finally中定义返回语句的情况,如下例:

package scalaTestobject Test6{    def main(args:Array[String]):Unit = {        println(f)    }    def f() = {        try{1}finally{2}    }}

结果:

145829_9QOF_168814.jpg

我们再来看看另一个很特别的例子

package scalaTestobject Test6 {    def main(args:Array[String]):Unit = {        println(f)    }    def f():Int = {        try{return 1}finally{return 2}    }}

(注: scala中使用return进行返回值的时候,方法上一定要注明返回类型!!!),我们再来看看结果(很震惊!!!!!!相当震惊!!!!):

150258_mj9T_168814.jpg

这两个例子足以令大多数程序员震惊!!!因此通常最好还是避免用finally子句返回值,而是把它理解为确保某些操作发生的途径,如关闭打开文件。

转载于:https://my.oschina.net/fhd/blog/275698

你可能感兴趣的文章
一篇文章全面了解监控知识体系
查看>>
部署mongodb做replica set分布式
查看>>
linux如何查看文件夹大小
查看>>
关键字 输入效果和样式
查看>>
用Js的eval解析JSON中的注意点
查看>>
玩转树莓派——升级NOOBS离线安装介质到Raspbian 4.9和Windows 10 IoT C
查看>>
php使用GD库合并简单图片并变动部分颜色
查看>>
【用jersey构建REST服务】系列文章
查看>>
ElasticSearch最新权威指南中文翻译版!
查看>>
java jdk简单解析
查看>>
ARM 曝光32位 1mm x 1mm CPU
查看>>
QNX Neutrino OS 6.5 SP1发布
查看>>
原型以及原型链
查看>>
王利芬 2011
查看>>
疯狂Spring Cloud连载(9)——RestTemplate的负载均衡原理
查看>>
疯狂Spring Cloud连载(27)Apache Kafka框架
查看>>
Hadoop2.4.1伪分布式的搭建
查看>>
https方式使用TortoiseGit设置git@osc密码长期存储
查看>>
由于多个切面pointcut重叠造成的事务的问题。
查看>>
JAVA懒开发:lombok的使用
查看>>