一、概念
- “异常”这个词有“我对此感到意外”的意思。问题出现了,你也许并不清楚该如何处理,但你的确知道不应该置之不理;你要停下来,看看是不是有别人或在别的地方,能够处理这个问题。只是在当前的环境中还没有足够的信息来解决这个问题,所以就把这个问题提交到一个更高级别的环境中,在这里将作出正确的决定。
二、基本知识
2.1 基本异常
- 当抛出异常后,首先,同Java中其它的对象创建一样,将使用 new在堆上创建异常对象。然后,当前的执行路径(它不能继续下去了)被终止,并且从当前环境中弹出对异常对象的引用。此时,异常处理机制接管程序,并开始寻找一个恰当的地方来继续执行程序。这个恰当的地方就是异常处理程序,它的任务是将程序从错误状态中恢复,以使程序能要么换一种方式运行,要么继续运行下去。异常允许我们(如果没有其它手段)强制程序停止运行,并告诉我们出现了什么问题,或者(理想状态下)强制程序处理问题,并返回到稳定状态。
在基本异常的基础之上,我们还需要知道异常的参数:
- 我们总是用 new 在堆上创建异常对象,这也伴随着存储空间的分配和构造器的调用。所有标准异常类都有两个构造器:一个是默认构造器;另一个是接受字符串作为参数,以便能把相关信息放入异常对象的构造器:
throw new NullpointerException("t = null ");
- 在使用 new 创建异常对象之后,此对象的引用将传给 throw。将会返回一个异常对象然后退出方法或作用域。
- 能够抛出任意类型的Throwable对象,它是异常类型的根类。通常,对于不同类型的错误,要抛出相应的异常。错误信息可以保存在异常对象内部或者使用异常类的名称来暗示。上一层环境通过这些信息来决定如何处理异常。(通常,异常对象中仅有的信息就是异常类型,除此之外不包含任何有意义的内容。)
2.2 捕获异常
try 块捕获异常
如果在方法内部抛出了异常(或者在方法内部调用的其他方法抛出了异常),这个方法将在抛出异常的过程中结束。要是不希望方法就此结束,可以在方法内设置一个特殊的块来捕获异常。
catch块处理异常
当然,抛出的异常必须在某处得到处理。这个“地点”就是异常处理程序,而且针对每个要捕获的异常,得准备相应的处理程序。异常处理程序紧跟在 try 块之后,以关键字 catch 表示:
try{//Code that might generate exceptions }catch(Type1 id1){//handle exceptions of Type1 }catch(Type2 id2){//handle exceptions of Type2 } //etc...
异常处理程序必须紧跟在 try 块之后。当异常被抛出时,异常处理机制将负责搜寻参数与异常类型相匹配的第一个处理程序。然后进入 catch 子句执行,此时认为异常得到了处理。一旦 catch 子句结束,则处理程序的查找过程结束。注意,只有匹配的 catch 子句才能得到执行。
两种异常处理模型: 终止模型、恢复模型
终止模型: 一旦异常被抛出,就表明错误已经无法挽回,也不能回来继续执行。
恢复模型: 异常处理程序的工作是修正错误,然后重新尝试调出问题的方法,并认为第二次能成功。 该种模型时,不能再遇见错误时就抛出异常,而是调用方法来修正,或者把try块放在while循环里,这样不断的进入try块直到得到满意的结果。
2.3 创建自定义异常
通过自定义MyException继承自Exception来创建自定义的异常。
class MyException extends Exception{public MyException(){}public MyException(String in){super(in);} }
并在catch中通过:
e.printStackTrace()
将异常写入到System.err(标准错误流),在debug的时候会显示错误的函数和行号(这是对System.out的优势)。
(它将打印“从方法调用处直到异常抛出处”的方法调用序列)
栈轨迹:
printStackTrace方法也可以通过getStackTrace()方法来访问,这个方法将返回一个由栈轨迹中的元素构成的数组,其中每一个元素都将表示栈中的一帧。
元素0是栈顶元素,并且是调用序列中的最后一个方法调用。
通过如下代码打印 栈轨迹:
try {f();} catch (MyException e) {// e.printStackTrace();for(StackTraceElement ste : e.getStackTrace()){Log.d(TAG, "onClick: "+ste.getMethodName());}}
得到的结果如下:
2.4 异常说明
如果调用某个方法,方法里的代码产生了异常却没有进行处理,编译器会发现这个问题: 要么处理这个异常,要么在函数异常说明中表明此方法将产生异常。
如下图所示: 1、函数声明加: throws MyException 2、函数中 增加 try catch 处理异常。
2.5 try catch中有return,final?
当try/catch代码中有return语句,那么此时的final是否还会继续执行?
1、 当try catch中有return 语句,在执行return之前将需要return的结果保存在一个临时变量中,然后去执行finally代码块,执行完之后再执行return。
2、 1中情况有个前提条件是finally中没有return语句,如果finally代码块中也有return,那么会执行finally中的return,不会执行try/catch中的。
int testFinallyReturn(){int x = 1;try{x++;return x;}catch (Exception e){return x;}finally {++x;return x;}}
运行结果:
if(exist("return x") in finally){
return result : 2 ;
}else{
return result : 3 ;
}