Java异常在日常的开发中简直是司空见惯了,但自己还是想做一个整理,看这篇文章的人,如果觉得有所收获,那就更好了。
自己想从3方面来介绍java异常;
1、异常的体系结构,
2、异常认识,
3、一般异常处理的原则。
一、异常的体系结构
Throwable类是所有异常的始祖,它有两个直接子类Error / Exception。
Error 一般是指java虚拟机生成并抛出的相关问题,如系统崩溃(系统错误)、虚拟机出错误、动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断,通常应用程序无法处理这些错误,因此应用程序不应该捕获Error对象,也无须在其throws子句中声明该方法抛出任何Error或其子类。
Exception 的一种分类:Checked异常和Runtime异常。所有RuntimeException类及其子类的实例被称为Runtime异常,不属于该范畴的异常则被称为CheckedException。
CheckedException:代表程序不能控制的无效外界情况。可以被处理的异常,如果没有处理则无法编译。没有完善错误处理的代码根本没有机会被执行。除了Error以及RuntimeException及其子类,CheckedException处理方式有两种:
1、当前方法知道如何处理该异常,则调用try...catch...显示捕获
2、当前方法不知道如何处理,则在定义该方法声明抛出异常
常见的CheckedException有ClassNotFoundException, NamingException, ServletException, SQLException, IOException等。
RuntimeException:所有RuntimeException的实例及其子类的实例。这些异常可以选择捕获处理、也可以不处理,一般由程序逻辑错误引起(应尽量从逻辑角度避免此类异常的发生)。
常见的RuntimeException有ArithmeticException、ArrayStoreExcetpion、ClassCastException、NullPointerException、IndexOutOfBoundsException、IllegalArgumentException、NegativeArraySizeException、NumberFormatException、SecurityException、UnsupportedOperationException等等
Exception的另一种分类:CheckedException和UncheckedException。
CheckedException:同上。【代表程序不能直接控制的无效外界情况(如用户输入,数据库问题,网络异常,文件丢失等),除了Error和RuntimeException及其子类之外,如:ClassNotFoundException, NamingException, ServletException, SQLException, IOException等。 需要try catch处理或throws声明抛出异常。 】
UncheckedException: 指的是程序的瑕疵或逻辑错误,并且在运行时无法恢复,包括Error与RuntimeException及其子类,如:OutOfMemoryError, UndeclaredThrowableException, IllegalArgumentException, IllegalMonitorStateException, NullPointerException, IllegalStateException, IndexOutOfBoundsException等;语法上不需要声明抛出异常。
综上:CheckedException 需要调用try...catch...显示捕获,而RuntimeException 不需要捕获;CheckedException可以继续执行下去,不能继续执行下去的就是UncheckedException。
二、异常的认识
Java中的异常用对象来表示。Java对异常的处理是按异常分类处理的,不同异常有不同的分类,每种异常都对应一个类型(class),每个异常都对应一个异常(类的)对象,这样就可以将异常情况与异常类一一对应,从抛出的异常类就可以知道是什么异常了。
Java有2种异常,一种是Java语言本身定义的一些基本异常类型(一般我们熟悉的异常类都是),一种是用户通过继承Exception类或者其子类自己定义的异常,这类异常主要是针对项目本身情况定义的异常。
Java异常处理主要通过关键字try、catch、throw、throws、finally进行管理。基本过程是用try语句块包住要监视的语句,如果在try语句块内出现异常,则异常会被抛出,你的代码在catch语句块中可以捕获到这个异常并做处理;还有以部分系统生成的异常在Java运行时自动抛出。你也可以通过throws关键字在方法上声明该方法要抛出异常,然后在方法内部通过throw抛出异常对象。finally语句块会在方法执行return之前执行。
三、异常处理
Java异常处理涉及到五个关键字,分别是:try、catch、finally、throw、throws。下面将骤一介绍,通过认识这五个关键字,掌握基本异常处理知识。
1、try:它里面放置可能引发异常的代码
2、catch:后面对应异常类型和一个代码块,用于表明该catch块用于处理这种类型的代码块,可以有多个catch块。
3、finally:主要用于回收在try块里打开的物理资源(如数据库连接、网络连接和磁盘文件),异常机制总是保证finally块总是被执行。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
(对于这个说的顺序,大师兄我做了个测试,可以看下,链接:亲自测试下try catch finally 的执行顺序)
4、throw:用于抛出一个实际的异常,可以单独作为语句使用,抛出一个具体的异常对象。
5、throws:用在方法签名中,用于声明该方法可能抛出的异常。
其中, try、catch、finally三个语句块应注意的问题
(1)try、catch、finally三个语句块均不能单独使用,三者可以组成 try...catch...finally、try...catch、try...finally三种结构,catch语句可以有一个或多个,finally语句最多一个。
(2)try、catch、finally三个代码块中变量的作用域为代码块内部,分别独立而不能相互访问。如果要在三个块中都可以访问,则需要将变量定义到这些块的外面。
(3)多个catch块时候,最多只会匹配其中一个异常类且只会执行该catch块代码,而不会再执行其它的catch块,且匹配catch语句的顺序为从上到下,也可能所有的catch都没执行。
(4)先Catch子类异常再Catch父类异常。
(5)Finally:当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。在以下4种特殊情况下,finally块不会被执行:
1)在finally语句块中发生了异常。
2)在前面的代码中用了System.exit()退出程序。
3)程序所在的线程死亡。
4)关闭CPU。
其中,throw与throws关键字的区别
(1)throw关键字是用于方法体内部,用来抛出一个Throwable类型的异常。如果抛出了检查异常,则还应该在方法头部声明方法可能抛出的异常类型。该 方法的调用者也必须检查处理抛出的异常。如果所有方法都层层上抛获取的异常,最终JVM会进行处理,处理也很简单,就是打印异常消息和堆栈信息。如果抛出 的是Error或RuntimeException,则该方法的调用者可选择处理该异常。
(2)throws关键字用于方法体外部的方法声明部分,用来声明方法可能会抛出某些异常。仅当抛出了检查异常,该方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出,而不是囫囵吞枣一般在catch块中打印一下堆栈信息做个勉强处理。