十二、通过异常处理错误 

Java的基本理念是“结构不佳的代码不能运行”。

Java中的异常处理的目的在于通过使用少于目前数量的代码来简化大型、可靠的程序的生成,并且通过这种方式可以使你更加自信:你的程序中没有未处理的错误。

1.概念

  C以及其他早期语言常常具有多种错误处理模式,这些模式往往建立在约定俗成的基础上,而并不属于语言的一部分。通常会返回某个特殊值或者设置某个标志,并且假定接收者将对这个返回值或标志进行检查,以判定是否发生了错误。然而,对于构造大型、健壮、可维护的程序而言,这种错误处理模式已经成为了主要障碍。

  解决的办法是,用强制规定的形式来消除错误处理过程中随心所欲的因素。这种做法由来已久,对异常处理的实现可以追溯到20世纪60年代的操作系统,甚至于BASIC语言中的on error goto语句。而C++的异常处理机制基于AdaJava中的异常处理则建立在C++的基础之上。

  使用异常所带来的一个相当明显的好处是,它往往能够降低错误处理代码的复杂度。如果不使用异常,那么就必须检查特定的错误,并在程序中的许多地方去处理它。而如果使用异常,那就不必在方法调用处进行检查,因为异常机制将保证能够捕获这个错误。并且,只需在一个地方处理错误,即所谓的异常处理程序中。这种方式不仅节省代码,而且把“描述在正常执行过程中做什么事”的代码和“出了问题怎么办”的代码相分离。

  

2.基本异常

  异常情形是指阻止当前方法或作用域继续执行的问题。把异常情形与普通问题相区分很重要,所谓的普通问题是指,在当前环境下能得到足够的信息,总能处理这个错误。而对于异常情形,就不能继续下去了,因为在当前环境下无法获得必要的信息来解决问题。你所能做的就是从当前问题跳出,并且把问题提交给上一级环境。这就是抛出异常时所发生的事情。

  当抛出异常后,有几件事会随之发生。首先,同Java中其他对象的创建一样,将使用new在堆上创建异常对象。然后,当前的执行路径将终止,并且从当前环境中弹出对异常对象的引用。此时,异常处理机制接管程序,并开始寻找一个恰当的地方来继续执行程序。这个恰当的地方就是异常处理程序,它的任务是将程序从错误状态中恢复,以使程序能要么换一种方式运行,要么继续运行下去。

  ①异常参数

  所有标准异常类都有两个构造器:一个是默认构造器;另一个是接受字符串作为参数,以便能把相关信息放入异常对象的构造器。

  通常,异常对象中仅有的信息就是异常类型,除此之外不包含任何有意义的内容。

3.捕获异常

  要明白异常是如何被捕获的,必须首先理解监控区域的概念。它是一段可能产生异常的代码,并且后面跟着处理这些异常的代码。

  ①try块

  如果在方法内部抛出了异常,这个方法将在抛出异常的过程中结束。要是不希望方法就此结束,可以在方法内设置一个特殊的块来捕获异常。因为在这个块里“尝试”各种方法调用,所以称为try块。

try {
//Here's the code
}

  ②异常处理程序 

  异常处理程序紧跟在try块后面,以关键字catch表示。

4.创建自定义异常

  要自己定义异常类,必须从已有的异常类继承,最好是选择意思相近的异常类。

  对异常来说,最重要的部分就是类名。

5.异常说明 

  异常说明属于方法声明的一部分,紧跟在形式参数列表之后。

6.捕获所有的异常 

  可以只写一个异常处理程序来捕获所有类型的异常。通过捕获异常类型的基类Exception就可以做到这一点。

  printStackTrace()方法所提供的信息可以通过getStackTrace()方法来直接访问,这个方法将返回一个由栈轨迹中的元素所构成的数组,其中每一个元素都表示栈中的一帧。元素0是栈顶元素,并且是调用序列中的最后一个方法调用。

  异常链

  常常会想要在捕获一个异常后抛出另一个异常,并且希望把原始异常的信息保存下去,这被称为异常链。现在所有的Throwable的子类在构造器中都可以接受一个cause对象作为参数。这个cause就用来表示原始异常,这样通过把原始异常传递给新的异常,使得即使在当前位置创建并抛出了新的异常,也能通过这个异常链追踪到异常最初发生的位置。

  只有三种基本的异常类提供了带cause参数的构造器,分别是ErrorExceptionRuntimeException。如果要把其他类型的异常链接起来,应该使用initCause()方法而不是构造器。

  

7.Java标准异常 

  Throwable这个类被用来表示任何可以作为异常被抛出的类。Throwable对象可分为两种类型:Error用来表示编译时和系统错误;Exception是可以被抛出的基本类型。Java程序员关心的基类型通常是Exception。

  异常的基本概念是用名称代表发生的问题,并且异常的名称应该可以望文知意。

  ①特例:RuntimeException 

  运行时异常会自动被Java虚拟机抛出,被称为“不受检查异常”。

  如果RuntimeException没有被捕获而直达main(),那么在程序退出前将调用异常的printStackTrace()方法。

  RuntimeException代表的是编程错误:

  1)无法预料的错误。例如null引用

  2)作为程序员,应该在代码中进行检查的错误。

8.使用finally进行清理 

  无论try块中的异常是否被抛出,finally子句里的代码总能运行。

  当要把除内存之外的资源恢复到它们的初始状态时,就要用到finally子句。这种需要清理的资源包括:已经打开的文件或网络连接,在屏幕上画的图形,甚至可以是外部世界的某个开关。

  当涉及break和continue语句的时候,finally子句也会得到执行。

  当用某些特殊的方式使用finally子句,会出现异常丢失的情况。例如在finally子句中return。

9.异常的限制

  当覆盖方法的时候,只能抛出在基类方法的异常说明里列出的那些异常。这意味着,当基类使用的代码应用到其派生类对象的时候,一样能够工作,异常也不例外。

  异常限制对构造器不起作用。但派生类构造器的异常说明必须包含基类构造器的异常说明。派生类构造器不能捕获基类构造器抛出的异常。

  不能基于异常说明来重载方法。一个出现在基类方法的异常说明中的异常,不一定会出现在派生类方法的异常说明中。

10.构造器 

  对于在构造阶段可能会抛出异常,并且要求清理的类,最安全的使用方式是使用嵌套的try子句。

11.异常匹配

  抛出异常的时候,异常处理系统会按照代码的书写顺序找出“最近”的处理程序。找到匹配的处理程序之后,它就认为异常将得到处理,查找不再继续。

  派生类的对象也可以匹配其基类的处理程序。

12.异常使用指南 

  1)在恰当的级别处理问题。

  2)解决问题并且重新调用产生异常的方法。

  3)进行少许修补,然后绕过异常发生的地方继续执行。

  4)用别的数据进行计算,以代替方法预计会返回的值。

  5)把当前运行环境下能做的事情尽量做完,然后把相同或不同的异常抛到更高层。

  6)终止程序。

  7)进行简化。

  8)让类库和程序更安全。

13.总结   以上简略了许多内容,许多更复杂一些的问题不是一言两语。

  异常可以帮助我们制造出更多健壮的程序,是相当重要又不那么复杂的知识。应该熟练掌握

Java编程思想 学习笔记12的更多相关文章

  1. [Java编程思想-学习笔记]第3章 操作符

    3.1  更简单的打印语句 学习编程语言的通许遇到的第一个程序无非打印"Hello, world"了,然而在Java中要写成 System.out.println("He ...

  2. Java编程思想 学习笔记1

    一.对象导论 1.抽象过程 Alan Kay曾经总结了第一个成功的面向对象语言.同时也是Java所基于的语言之一的Smalltalk的五个基本特性,这些特性表现了纯粹的面向对象程序设计方式 1)万物皆 ...

  3. [Java编程思想-学习笔记]第1章 对象导论

    1.1  抽象过程 Java是一门面向对象的语言,它的一个优点在于只针对待解问题抽象,而不用为具体的计算机结构而烦心,这使得Java有完美的移植性,也即Java的口号"Write Once, ...

  4. Java编程思想 学习笔记11

    十一.持有对象  通常,程序总是根据运行时才知道的某些条件去创建新对象.在此之前,不会知道所需对象的数量,甚至不知道确切的类型. Java实用库还提供了一套相当完整的容器类来解决这个问题,其中基本的类 ...

  5. Java编程思想 学习笔记10

    十.内部类  可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一种非常有用的特性,因为它允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性.然而必须要了解,内部类和组合是 ...

  6. Java编程思想学习笔记——类型信息

    前言 运行时类型信息(RTTI:Runtime Type Information)使得我们可以在程序运行时发现和使用类型信息. Java在运行时识别对象和类的信息的方式: (1)一种是RTTI,它假定 ...

  7. Java编程思想 学习笔记7

    七.复用类 1.组合语法 在新的类中产生现有类的对象.由于新的类是由现有类的对象所组成,所以这种方法叫做组合. 类中域为基本类型时能够自动被初始化为零.对象引用被初始化为null. 编译器不是简单地为 ...

  8. Java编程思想 学习笔记5

    五.初始化与清理 1.用构造器确保初始化  在Java中,通过提供构造器,类的设计者可确保每个对象都会得到初始化.创建对象时,如果其类具有构造器,Java就会在用户有能力操作对象之前自动调用相应的构造 ...

  9. Java编程思想 学习笔记4

    四.控制执行流程 1.true和false 所有条件语句都利用条件表达式的真或假来决定执行路径.注意Java不允许我们将一个数字作为布尔值使用. 2.if-else 3.迭代 while.do-whi ...

随机推荐

  1. Kitematic when login show Error:Tunning socket could not be established

    https://cn.bing.com/search?q=tunning+socket+could+not+be+established&qs=n&form=QBRE&sp=- ...

  2. VM虚拟机—JVM内存

    JVM在运行时将数据划分为了5个区域来存储,这5个区域图示如下: 其中方法区和堆对是所有线程共享的内存区域:而java栈.本地方法栈和程序员计数器是运行时线程私有的内存区域. 首先我们熟悉一下一个 J ...

  3. JavaScript——变量

    本文简述了JavaScript变量的数据类型,以及变量类型检测与类型转换 一.介绍 JavaScript的变量有6种数据类型,包含5种原始类型和1种对象类型.本人比较喜欢用逻辑图的形式总结知识点,这样 ...

  4. Baltic Dry Index

    波罗的海干散货指数(Baltic Dry Index,缩写BDI),是航运业的经济指标,它包含了航运业的干散货交易量的转变. BDI波罗的海指数是由几条主要航线的即期运费(Spot Rate)加权计算 ...

  5. caffe运行错误: im2col.cu:61] Check failed: error == cudaSuccess (8 vs. 0) invalid device function

    错误: im2col.cu:61] Check failed: error == cudaSuccess (8 vs. 0)  invalid device function 原因:由于Makefil ...

  6. BZOJ 4032: [HEOI2015]最短不公共子串

    4032: [HEOI2015]最短不公共子串 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 446  Solved: 224[Submit][Sta ...

  7. sharepoint my site setting

    参考这个guide : http://technet.microsoft.com/en-us/library/ee624362.aspx User profile service 不能打开, 原因是s ...

  8. WEB入门之十三 jQuery选择器

    学习内容 jQuery层次选择器 jQuery属性选择器 jQuery表单选择器 jQuery过滤选择器 能力目标 熟悉jQuery各种选择器的使用场合 能熟练使用jQuery各种选择器 本章简介 上 ...

  9. 前端学习 -- Html&Css -- 框架集

    框架集和内联框架的作用类似,都是用于在一个页面中引入其他的外部的页面,框架集可以同时引入多个页面,而内联框架只能引入一个,在h5标准中,推荐使用框架集,而不使用内联框架. 使用frameset来创建一 ...

  10. 省选模拟赛第四轮 B——O(n^4)->O(n^3)->O(n^2)

    一 稍微转化一下,就是找所有和原树差距不超过k的不同构树的个数 一个挺trick的想法是: 由于矩阵树定理的行列式的值是把邻接矩阵数值看做边权的图的所有生成树的边权乘积之和 那么如果把不存在于原树中的 ...