文档章节

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

柳哥
 柳哥
发布于 2014/06/07 14:36
字数 1293
阅读 87
收藏 0
点赞 0
评论 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
python浓缩(10)

1 . 从 Python 1.5 开始, 所有的标准异常都使用类来实现. 本章将介绍什么是异常, 异常处理, 以及 Python 对异常的支持. 我们还会介绍如何在代码里生成异常. 最后, 我们会涉及如何创建自定义的...

人生如梦19
2016/04/12
90
0
scala函数式编程

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

泡海椒
2016/04/09
41
0
第十章,异常和错误

try 语句有两种主要形式: try-except 和 try-finally . 这两个语句是互斥的,也就是说你 只能使用其中的一种. 一个 try 语句可以对应一个或多个 except 子句, 但只能对应一个 finally 子句, 或...

happyliferao
2015/10/09
8
0
Python自动化运维之异常处理

1、异常 异常就是非正常状态,在Python中使用异常对象来表示异常。若程序在编译或运行过程中发生错误,程序的执行过程就会发生改变,抛出异常对象,程序流进入异常处理。如果异常对象没有被处...

炫维
06/26
0
0
ParisGabriel:Python全栈工程师(0基础到精通)教程 第二十一课(包、模块 的导入)

ParisGabriel 每天坚持手写 一天一篇 决定坚持几年 为了梦想为了信仰                         Python人工智能从入门到精通 补充:包的相对导入 只对后两种导入方式有...

ParisGabriel
07/19
0
0
c++教程(二十三: Exceptions)

Exceptions(异常) Exceptions 异常提供了一种方法来对程序中的异常情况(如运行时错误)进行响应,将控制传递给称为handlers处理器的特殊函数。 若要捕获异常,则在异常检查下放置一部分代...

on2way
2017/02/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Mybatis收集配置

一、Mybatis取Clob数据 1、Mapper.xml配置 <resultMap type="com.test.User" id="user"> <result column="id" property="id"/> <result column="json_data" property="jsonData" ......

星痕2018
14分钟前
0
0
centos7设置以多用户模式启动

1、旧版本linux系统修改inittab文件,在新版本执行vi /etc/inittab 会有以下提示 # inittab is no longer used when using systemd. # # ADDING CONFIGURATION HERE WILL HAVE NO EFFECT ON......

haha360
45分钟前
0
0
OSChina 周日乱弹 —— 红薯,五年间我对你不离不弃

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ andonny :分享周二珂的单曲《孤独她呀》 《孤独她呀》- 周二珂 手机党少年们想听歌,请使劲儿戳(这里) @孤星闵月 :没事干,看一遍红楼梦...

小小编辑
51分钟前
116
8
Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式 Factory工厂模式 Singleton单例模式 Delegate委派模式 Strategy策略模式 Prototype原型模式 Template模板模式 Spring5 beans 接口实例化 代理Bean操作 ...

小致dad
今天
0
0
SpringBoot | 第十章:Swagger2的集成和使用

前言 前一章节介绍了mybatisPlus的集成和简单使用,本章节开始接着上一章节的用户表,进行Swagger2的集成。现在都奉行前后端分离开发和微服务大行其道,分微服务及前后端分离后,前后端开发的...

oKong
今天
9
0
Python 最小二乘法 拟合 二次曲线

Python 二次拟合 随机生成数据,并且加上噪声干扰 构造需要拟合的函数形式,使用最小二乘法进行拟合 输出拟合后的参数 将拟合后的函数与原始数据绘图后进行对比 import numpy as npimport...

阿豪boy
今天
17
0
云拿 无人便利店

附近(上海市-航南路)开了家无人便利店.特意进去体验了一下.下面把自己看到的跟大家分享下. 经得现场工作人员同意后拍了几张照片.从外面看是这样.店门口的指导里强调:不要一次扫码多个人进入....

周翔
昨天
1
0
Java设计模式学习之工厂模式

在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

路小磊
昨天
244
1
npm profile 新功能介绍

转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

durban
昨天
1
0
Serial2Ethernet Bi-redirection

Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

zungyiu
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部