文档章节

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

柳哥
 柳哥
发布于 2014/06/07 14:36
字数 1293
阅读 90
收藏 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子句返回值,而是把它理解为确保某些操作发生的途径,如关闭打开文件。

© 著作权归作者所有

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

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

finndai
2016/10/18
28
0
看书 Python 源码分析笔记 (五)

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

刘军兴
2015/12/21
78
0
Kotlin in Action 学习笔记 (1)

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

realxz
2017/12/14
0
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

没有更多内容

加载失败,请刷新页面

加载更多

20180920 rzsz传输文件、用户和用户组相关配置文件与管理

利用rz、sz实现Linux与Windows互传文件 [root@centos01 ~]# yum install -y lrzsz # 安装工具sz test.txt # 弹出对话框,传递到选择的路径下rz # 回车后,会从对话框中选择对应的文件传递...

野雪球
今天
1
0
OSChina 周四乱弹 —— 毒蛇当辣条

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ 达尔文:分享花澤香菜/前野智昭/小野大輔/井上喜久子的单曲《ミッション! 健?康?第?イチ》 《ミッション! 健?康?第?イチ》- 花澤香菜/前野智...

小小编辑
今天
7
3
java -jar运行内存设置

java -Xms64m #JVM启动时的初始堆大小 -Xmx128m #最大堆大小 -Xmn64m #年轻代的大小,其余的空间是老年代 -XX:MaxMetaspaceSize=128m # -XX:CompressedClassSpaceSize=6...

李玉长
今天
3
0
Spring | 手把手教你SSM最优雅的整合方式

HEY 本节主要内容为:基于Spring从0到1搭建一个web工程,适合初学者,Java初级开发者。欢迎与我交流。 MODULE 新建一个Maven工程。 不论你是什么工具,选这个就可以了,然后next,直至finis...

冯文议
今天
2
0
RxJS的另外四种实现方式(四)——性能最高的库(续)

接上一篇RxJS的另外四种实现方式(三)——性能最高的库 上一篇文章我展示了这个最高性能库的实现方法。下面我介绍一下这个性能提升的秘密。 首先,为了弄清楚Most库究竟为何如此快,我必须借...

一个灰
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部