[N天一练]java exception

         java exception是java有别于其他语言的一个重要特性,在平时的工作中相信大家经常会用到,目前大家对于exception的使用也存在各种各样的争议,最近有时间整理了一下。我们知道exception在java中的体系结构:

       [N天一练]java exception_第1张图片

        无论是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存在以下的优势:

  1. 层次分明,try、catch、finally三个区块各自处理什么内容清晰明确;
  2. catch所捕获的Exception更面向对象,在编程时能够面向某类异常来编写出错逻辑的代码;
  3. 错误日志详细,利于排错。我们知道异常会将其调用堆栈保存下来,出错时会全部打印出来,是我们查找问题的一个重要依据;
  4. 使用异常可以不中断程序,使程序在异常发生后仍能继续执行,这是我们在某些大循环的处理任务中经常会使用的,不必为某一次的失败而终止程序。
   而不想使用异常的原因是:创建一个异常对象的成本相当的高,是创建一个普通对象的几十倍。究其原因是因为异常在每次创建时会调用fillInStatckTrace()方法 填充调用的堆栈信息,这个过程相当的耗性能,如果你的程序中某个逻辑会频繁的抛异常,对你的服务器性能将会有一个很大的影响。
   如果你在使用异常时不需要对异常的堆栈信息有太详细的了解,可以通过重写这个方法来提高性能。
   checked VS unchecked的争论在于,到底是在项目中使用运行时的异常好还是非运行时的异常好。

   支持使用unchecked的人认为使用checked异常会使代码中遍布try-catch-finally的代码,并且在方法声明中的throws中要不断的添加新抛出的异常,不符合OCP;而支持使用checked的exception的人则认为使用unchecked异常容易使人忘记去处理异常,而编译器也不会提醒你,对开发不利。

   以上。

你可能感兴趣的:([N天一练]java exception)