java exception是java有别于其他语言的一个重要特性,在平时的工作中相信大家经常会用到,目前大家对于exception的使用也存在各种各样的争议,最近有时间整理了一下。我们知道exception在java中的体系结构:
无论是error还是exception都继承自Throwable类。
Error往往是一些合理程序不能截获的严重错误,往往会导致jvm中断终止,如OutOfMemoryError错误。程序员也无法在程序中处理这类错误。
Exception是程序编译和运行时出现的错误,会由虚拟机来通知程序出错,程序员可以在程序中对此类错误进行处理。而Exception又可分为两类:运行时异常和非运行时异常。
运行时异常,全部继承自RuntimeException类。运行时异常也叫unchecked异常。为什么叫它unchecked呢?就是这类异常一般程序员不需要去try-catch,因为就算你catch到了,你对它一般也只有无能为力四个字,并且这类异常往往可以通过程序逻辑来避免发生,如NullpointerException,IndexOutOfBoundsException等。
非运行时异常,也叫编译期异常,也叫checked异常。也就是说这类异常需要你去try-catch的,如果有个方法声明中throws了某类异常,而你的代码中没有进行try-catch,则编译期就会直接报错。这也是java有别于C#等语言的地方,C#是没有checked异常的。
exception是由try-catch-finally来处理的,如下:
try{ .... }catch(Exception e){ .... }finally{ .... }其中try区块中的内容就是有可能会抛出异常的代码块;
而catch区块后面的括号里写的是所要捕获的异常类型,后面的代码是在捕获了该类异常后所要执行的代码。异常是有上下层级关系的,而catch会去捕获后面括号里所给出的异常类型及其所有子类。所以我们在catch多个异常时,需要将子类写在父类的前面,以使子类的catch能够生效;而在不知道会出现什么异常的时候就会去捕获所有异常的父类Exception。
finally块中则是无法异常出现与否,都必须要执行的代码,即使在try区块或者catch区块有return,也会在return之前执行finally区块的内容。
而在捕获到异常后,处理时有一点要注意。我们知道在一个try-catch-finally区块中,如果会抛出多个异常时,则最终只会抛出最后抛出的那个异常,前面的异常将会被忽略,如下面的代码:
InputStream input = null; try { input = new FileInputStream("file.txt"); } catch (IOException e) { throw new RuntimeException(e); } finally { try { input.close(); } catch (IOException e) { throw new RuntimeException(e); } }如果file.txt不存在,则会抛出一个FileNotFoundException,被catch捕获到,然后将其包装成运行时异常抛出,然后执行finally内容,由于input完全没有被初始化,因此抛出了一个NullPointerException,因此最终上层调用代码抛出就是一个NullPointerException而不是 FileNotFoundException,所以我们在编程中要避免出现此类问题。
而在异常的使用中,一直有两个比较大的争论,那就是Exception VS return false和checked VS unchecked。
Exception VS retrun false的争论在于,对于一些场景,空间是抛出异常比较好还是返回一个结果对象好?倾向于使用Exception的原因在于Exception存在以下的优势:
支持使用unchecked的人认为使用checked异常会使代码中遍布try-catch-finally的代码,并且在方法声明中的throws中要不断的添加新抛出的异常,不符合OCP;而支持使用checked的exception的人则认为使用unchecked异常容易使人忘记去处理异常,而编译器也不会提醒你,对开发不利。
以上。