文档章节

内建控制结构之使用try表达式处理异常

柳哥
 柳哥
发布于 2014/06/07 14:36
字数 1293
阅读 93
收藏 0

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

package scalaTest
object 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")
    }
}

执行结果:

这段代码的意思是,如果n是偶数,将打印n的一半。如果n不是偶数,那么异常将被抛出。因此,无论怎么说,把抛出的异常当作任何类型的值都是安全的。任何使用经throw返回值的尝试都不会起作用,因此这样做不会有害处
从技术角度上来说,抛出异常的类型是Nothing。尽管throw不实际产生任何值,你还是可以把它当作表达式。这种小技巧或许看上去很怪异,但像在上面这样的例子里却常常很有用。If的一个分支计算值,另一个抛出异常并得到Nothing。整个if表达式的类型就是那个实际计算值的分支的类型(Nothing类型将在以后会讲到)。


捕获异常

package scalaTest

import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException

object 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 scalaTest

import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException

object 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 scalaTest

import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException

object 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 scalaTest

import java.net.URL
import java.net.MalformedURLException

object 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")
        }
    }
}

结果:

上例演示了如何尝试拆分URL,但如果URL格式错误就使用默认值。也就是,如果没有异常抛出,则对应于try子句;如果抛出异常并被捕获,则对应于相应的catch子句。如果异常被抛出但没被捕获,表达式就没有返回值
由finally子句计算得到的值,即使有也会被抛弃通常finally子句做一些诸如关闭文件之类的清理工作,它们不应该修改主函数体或catch子句中计算的值。
Scala的行为与java的差别仅在于java的try-finally不产生值。在java里,如果finally子句包含返回语句,或抛出一个异常,这个返回值或异常将“凌驾”于任何之前在try代码块或某个catch子句里产生的值或异常之上。
我们来测试一下,scala的finally中定义返回语句的情况,如下例:

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

结果:

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

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

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


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

© 著作权归作者所有

共有 人打赏支持
柳哥
粉丝 206
博文 405
码字总数 347782
作品 0
杭州
技术主管
私信 提问
Python核心编程第十章

10.1什么是异常 10.1.1错误 语法错误 :软件结构上有误,导致不能被解释器或编译器无法编译 逻辑错误:不完整或不合法的输入所致 10.1.2异常 程序出现了错误而在正常控制流以外采取的行为:1...

finndai
2016/10/18
28
0
Kotlin in Action 学习笔记 (1)

Kotlin 是以俄罗斯圣彼得堡附近的一座岛屿命名 Kotlin 是一门全新的针对 Java 平台的新编程的语言,百分之百与 Java 兼容,它是一门静态类型的语言,并且支持类型推导 先从书中的第一段代码来...

realxz
2017/12/14
0
0
看书 Python 源码分析笔记 (五)

第9章 Python 虚拟机中的一般表达式 这里一般表达式指对象创建语句, 打印语句等. if, while 等归为控制流语句于下一章. 简单内建对象的创建 示例 python 代码: i = 1 // int objects = "Pyt...

刘军兴
2015/12/21
78
0
【 转】__try,__except,__finally,__leave异常模型机制

转自:http://blog.csdn.net/wwl33695/article/details/8686458 导读: 从本篇文章开始,将全面阐述try,except,finally,leave异常模型机制,它也即是Windows系列操作系统平台上提供的SEH...

cxycappuccino
2015/04/20
0
0
scala函数式编程

 结构  学会使用Scala中主要的结构控制语句  数组  学会数组的声明与使用  映射  了解Scala中的映射的基础知识  包与引用 Scala控制结构  判断(if表达式)  循环(while/do...

泡海椒
2016/04/09
41
0

没有更多内容

加载失败,请刷新页面

加载更多

开始看《Java学习笔记》

虽然书买了很久,但一直没看。这其中也写过一些Java程序,但都是基于IDE的帮助和对C#的理解来写的,感觉不踏实。 林信良的书写得蛮好的,能够帮助打好基础,看得出作者是比较用心的。 第1章概...

max佩恩
昨天
11
0
Redux 三大原则

1.单一数据源 在传统的MVC架构中,我们可以根据需要创建无数个Model,而Model之间可以互相监听、触发事件甚至循环或嵌套触发事件,这些在Redux中都是不被允许的。 因为在Redux的思想里,一个...

wenxingjun
昨天
7
0
跟我学Spring Cloud(Finchley版)-12-微服务容错三板斧

至此,我们已实现服务发现、负载均衡,同时,使用Feign也实现了良好的远程调用——我们的代码是可读、可维护的。理论上,我们现在已经能构建一个不错的分布式应用了,但微服务之间是通过网络...

周立_ITMuch
昨天
4
0
XML

学习目标  能够说出XML的作用  能够编写XML文档声明  能够编写符合语法的XML  能够通过DTD约束编写XML文档  能够通过Schema约束编写XML文档  能够通过Dom4j解析XML文档 第1章 xm...

stars永恒
昨天
2
0
RabbitMQ学习(2)

1. 生产者客户端 void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, BasicProperties props, byte[] body) 1. 在生产者客户端发送消息时,首先......

江左煤郎
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部