发现错误的理想时机是在编译阶段。编译期间并不能找出所有的错误,余下的问题必须再运行期间解决。
1.概念
- 使用异常能够降低处理代码的复杂度。
2.基本异常
-
异常情形是指阻止当前方法或作用域继续执行的问题。
-
当抛出异常后,有几件事会随之发生。
- 同Java中其他对象的创建一样,将使用new在堆上创建异常对象。
- 然后当前的执行路径被终止,并且从当前环境中弹出对异常对象的引用。此时,异常处理机制接管程序,并开始寻找一个恰当的地方来继续执行程序。这个恰当的地方就是
异常处理程序
,它的任务是将程序从错误状态中恢复,以使程序能要么换一种方法运行,要么继续运行下去。
-
所有标准异常类都有两个构造器:一个是默认构造器,另一个是接受字符串作为参数。以便把相关信息放入异常对象的构造器。
throw new NullPointerExeception("t = null");
在使用new创建了异常对象之后,此对象的引用将传给throw。另外还能用抛出异常的方式从当前的作用域退出。这两种情况下,将会返回一个异常对象,然会退出方法或作用域。
-
Throwable
是异常类型的根类。
3.捕获异常
监控区域(guarded region)
是一段可能产生异常的代码,并且后面跟着处理这些异常的代码。
3.1 try块
-
如果在方法内部抛出异常,这个方法将在抛出异常的过程中结束。要是不希望方法就此结束,可以在方法内设置一个特殊的块来捕获异常。
try{ //code that might generate execeptions }
3.2 异常处理程序
- 抛出的异常必须在某处得到处理。异常处理程序紧跟在
try
块之后,以关键字catch
表示。 - 异常处理理论上有两种基本模型
-
终止模型
:一旦异常被抛出,就表明错误已无法挽回,也不能回来继续执行。 -
恢复模型
:异常处理程序的工作是修正错误,然后重新尝试调用出问题的方法,并认为第二次能成功。
-
- 偏向使用终止模型,恢复模型会导致代码的耦合。
4.创建自定义异常
- 建立新异常最简单的方法就是让编译器为你产生默认构造器,编译器会自动调用基类的默认构造器。
5.异常说明
-
关键字throws,后面接一个异常类型的列表
void f() throws TooBig,TooSmall,DivZero{ //... }
6.捕获所有异常
-
可以通过积累
Exception
捕获所有异常。 -
Exception是与编程有关的所有异常类的基类,可以调用它从其基类(Throwable)继承的方法:
String getMessage() String getLocalizedMessage()
用来获取详情信息,或用本地语言表示的详情信息
String toString()
返回对Throwable的简单描述,要是有详情描述的话,也会包含在内。
void printStackTrace() void printStackTrace(PrintStream) void printStackTrace(java.io.PrintWriter)
打印Throwable和Throwable的调用栈轨迹。
此外,对于异常类,使用
getClass()
可以获取表示此对象类型的对象。然后可以使用getName()
方法查询这个Class对象包含信息的名称,或者使用只产生类名称的getSimpleName()
方法。 -
printStackTrace()
方法所提供的信息可以通过getStackTrace()
方法来直接访问,这个方法返回一个由栈轨迹中的元素所构成的数组,其中每个元素都表示栈中的一帧。 -
重新抛出异常会把异常抛给上一级环境中的异常处理程序。异常对象的所有信息都得以保持,所以高一级环境中捕获此异常的处理程序可以从这个异常对象中的所有信息。
-
在捕获一个异常后抛出一个异常,并且希望把原始异常的信息保存下来,这被称为
异常链
。
7.Java标准异常
-
Throwable
对象可分为两种类型:-
Error
:表示编译时和系统错误,一般程序员不关心; -
Exception
:可以被抛出的基本类型,在Java类库,用户方法以及运行时故障中都可能抛出Exception异常。
-
-
RuntimeException
属于运行时异常,会自动被JVM抛出。它们也被称为“不受检查异常”,这种异常属于错误,将被自动捕获。 - 只能在代码中忽略
RuntimeException
及其子类的异常,其他类型异常的处理都是有编译器强制实施的。究其原因,RuntimeException
是编程错误。
8.使用finally进行清理
对于一些代码,在异常处理程序的后面加上 finally子句
,那么无论 try块
中的异常是否抛出,它们都能得到执行。
8.1 finally用来做什么
- finally子句能保证无论try块发生了什么,内存总能得到释放。
- 当要把除内存之外的资源恢复到它们的初始状态时,就要用到finally子句。这种资源包括:已经打开的文件或网络连接等等。
8.2 在return中使用finally
- 因为finally子句总会执行,所有在一个方法中。可以从多个点返回,并且可以保证重要的清理工作仍会执行。
8.3 缺憾:异常丢失
- 异常作为程序出错的标志,绝不应该被忽略,但它还是有可能被忽略。
- 在try块中包含另一个try-catch语句,可能会丢失外层的异常。
- 在finally子句中执行return
9.异常的限制
- 当覆盖方法的时候,只能抛出在基类方法的异常说明里那些列出的那些异常。
10.构造器
- 在大多数情况下,异常发生所有东西都能被正常清理。但是在涉及构造器时,由于构造器会吧对象设置成安全的初始状态,还会有别的动作,如打开文件等。这些动作只有在对象使用完毕并且用户调用了特殊的清理方法之后才能得以清理。如果在构造器内抛出异常,这些清理行为也许不能正常工作了。
11.异常匹配
- 抛出异常的时候,异常处理系统会按照代码的书写顺序找出最近的处理程序。找到匹配的处理程序之后,它就认为异常将得到处理,然后就不再继续查找了。
12.其他可选方式
13.异常使用指南
应该在下列情况使用异常:
- 在恰当的处理级别处理问题
- 解决问题并且重新调用产生异常的方法
- 进行少许修补,然后绕过异常发生的地方继续执行
- 用别的数据进行计算,以替代方法预计会返回的值
- 把当前运行环境下能做的事情尽量做完,然后把
相同的异常
重抛到更高层 - 把当前运行环境下能做的事情尽量做完,然后把
不同的异常
重抛到更高层 - 终止程序
- 进行简化
- 让类库和程序更安全
04/06/2019 :created
05/06/2019 :add 8,9,10,11,12,13
网友评论