JAVA异常知识总结
首先贴上JAVA常见的异常类之间的继承关系图
由图可以看出,基类为Throwable,Error和Exception类继承Throwable,Error下细分为AWTError(不太清楚),IOError(输入输出类),LinkageError(常见于JAR包冲突),ThreadDeath(线程类)。
Error由虚拟机生成并抛出,属于JVM系统内部错误或者资源耗尽等严重情况(程序无法处理的错误),属于JVM担负的责任,因而这类异常事件的发生后无法恢复或者无法对其进行捕获,error产生后最终将导致应用程序中断(JVM执行线程中断)。但是ERROR在某种场合下可以进行转译,即ERROR可以转译为Exception或者RuntimeException,从而挽回Error产生所带来的严重负面影响。
而Exception类下类别则非常多,首先分为两大类:RuntimeException以及非RuntimeException,(对应着Unchecked Exception以及Checked Exception)
RuntimeException类是Exception类的子类,它叫做运行时异常,Java中的所有运行时异常都会直接或者间接地继承自RuntimeException类。对于运行时异常(runtime exception),可以对其进行处理,也可以不处理。推荐不对运行时异常进行处理。
非RuntimeException:Java中凡是继承自Exception,而不继承自RuntimeException类的异常都是非运行时异常。一般来说,非RuntimeException一般都是外部错误,其必须给try{}catch...finally语句块捕获异常。也可以在可能发生该类型异常的方法写上throws 某一个Exception类型,如throws Exception,将异常抛出到外面一层去,可能最终由JVM进行处理。(如最常见的文件读写,数据库读写等操作)
简单的理解完异常处理后,如何处理出现的异常则显得非常的重要,如果在程序中不对异常进行处理,可能会让程序的所有异常都由JVM来处理,降低了性能,也可能直接造成程序假死等。
首先是对于异常处理的完整结构语法:(部分内容转载自http://blog.csdn.net/junlixxu/article/details/6096266#)
1 try{ 2 //(尝试运行的)程序代码 3 }catch(异常类型 异常的变量名){ 4 //括号里通常就是常见的XXXXXException e 5 }finally{ 6 //异常发生,方法返回之前,总是要执行的代码(注意是在方法返回前,很多地方笔试就考这个) 7 }
上述三个代码块中,Try语句块里所执行的代码受到JVM的异常监控,当异常发生时,JVM会抛出其异常对象。
catch语句块很显然就是负责捕获异常了,并且在该代码块里做异常的处理,需要一个Throwable(可抛出)类型的参数。并且catch代码块的个数是不限的,可以有多个,当异常发生时,catch会捕获异常,从上至下逐个将catch块参数指向抛出的异常对象,一旦匹配成功后,则停止匹配,下面的catch块也不会再去尝试了。通过这些异常对象可以获取异常发生时完整的JVM堆栈信息,以及异常信息和异常发生的原因等。。因此我们在写catch的异常类型时,需要将小范围的异常写在前,大范围的异常类型写在后。
finally语句块是紧跟catch语句后的语句块,这个语句块总是会在方法返回前执行, 而不管是否try语句块是否发生异常。并且这个语句块总是在方法返回前执行。 目的是给程序一个补救的机会。这样做也体现了Java语言的健壮性。
一些需要注意的小问题:
①try、catch、finally三个语句块均不能单独使用,三者可以组成 try...catch...finally、try...catch、
try...finally三种结构,catch语句可以有一个或多个,finally语句最多一个。
②try、catch、finally三个代码块中变量的作用域为代码块内部,分别独立而不能相互访问。
如果要在三个块中都可以访问,则需要将变量定义到这些块的外面。
③多个catch块时候,只会匹配其中一个异常类并执行catch块代码,而不会再执行别的catch块,
并且匹配catch语句的顺序是由上到下。
下面再简单的对throw和throws关键字进行简单的说明:throws通常用在方法声明的地方,用来声明某个方法可能会抛出的异常。仅当抛出了检查异常,方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出,而不是囫囵吞枣一般在catch块中打印一下堆栈信息做个勉强处理。
throw则是用在方法体里面,在用来抛出一个Throwable类型的异常,并且需要在方法头部声明可能抛出的异常类型。同时还要为抛出的异常进行处理,若该层的catch无法处理则层层抛出,最后由JVM进行处理,但JVM对该类异常的处理也仅仅是终止程序,并且打印异常信息以及堆栈的信息。
1 public static void testException() throws Exception{ 2 //抛出一个检查异常 3 throw new Exception("方法test3中的Exception"); 4 }
上面的例子很好的展示了throws和throw所运用的位置。
补充:Throwable类常用方法:
①printStackTrace();对象的堆栈跟踪输出至错误输出流,作为字段 System.err 的值。最常用的方法
②getCause();返回抛出异常的原因。如果 cause 不存在或未知,则返回 null。
③getMessage():返回异常的消息信息。