一、什么是异常数组
结构不佳的代码不能运行,这是Java的基本理念。性能
发现错误的理想时机是在编译期。然而,编译器并不能发现全部的错误,余下的问题就须要在程序运行时解决。这就须要错误能经过某种方式,把适当的信息 传递给特定的接收者处理。Java中的异常处理的目的在于经过使用少许的代码来简化大型、可靠的程序的生成,经过此方式让你的应用中没有未处理的错误,而 且它还带来了一个明显的好处:下降错误处理代码的复杂度。学习
异常,根据字面理解,有意外之意。把它置于代码层面来理解,即阻止了当前方法或做用域继续执行。spa
在Java中,异常被当作对象来处理,其基类是Throwable。线程
二、Java中的异常类型调试
Java从Throwable直接派生出Exception和Error。其中Exception是能够抛出的基本类型,在Java类库、方法以及运行时故障中均可能抛出Exception型异常。Exception表示能够恢复的异常,是编译器能够捕捉到的;Error表示编译时和系统错误,表示系统在运行期间出现了严重的错误,属于不可恢复的错误,因为这属于JVM层次的严重错误,所以这种错误会致使程序终止执行。Exception又分为检查异常和运行时异常。code
异常类的结构层次图以下:orm
典型的RuntimeException(运行时异常)包括NullPointerException, ClassCastException(类型转换异常),IndexOutOfBoundsException(越界异常), IllegalArgumentException(非法参数异常),ArrayStoreException(数组存储异常),AruthmeticException(算术异常),BufferOverflowException(缓冲区溢出异常)等;对象
非RuntimeException(检查异常)包括IOException, SQLException,InterruptedException(中断异常-调用线程睡眠时候),NumberFormatException(数字格式化异常)等。继承
而按照编译器检查方式划分,异常又能够分为检查型异常(CheckedException)和非检查型异常 (UncheckedException)。Error和RuntimeException合起来称为UncheckedException,之因此这么 称呼,是由于编译器不检查方法是否处理或者抛出这两种类型的异常,所以编译期间出现这种类型的异常也不会报错,默认由虚拟机提供处理方式。除了Error 和RuntimeException这两种类型的异常外,其它的异常都称为Checked异常。
三、Java如何处理异常
3.1 try-catch, try-finally, try-catch-finally
对于checked类型异常,咱们要么对它进行处理,要么在方法头使用throws抛出。
public static void createFile() throws IOException{ File file = new File("C:/test.txt"); if(!file.exists()){ file.createNewFile(); } } public static void main(String[] args) { try { createFile(); } catch (IOException ex) { // handle exception here } }
关于catch须要注意的几点:
1)、参数的异常类型必须是Throwable类或者其子类。
2)、从上往下的catch语句,其参数类型必须按照从子类到父类顺序,由于一旦匹配到一个类型,就会忽略日后的catch。好比IOException必须放到Exception前面,不然编译器会报错。
3)、能够有一个或者多个catch语句,甚至若是有finally语句的状况下,能够没有catch语句,如try-finally。
想要捕获多个异常,可使用多个catch语句,JDK7之后提供了另一种方式:多重捕获(multi-catch)。
try{ // other code } catch (IOException | SQLException ex) { throw ex; }
4)、不要忽略异常。空的catch块会使异常达不到应有的目的,除非诸如关闭FileInputStream的时候,由于你尚未改变文件的状态,所以没必要执行任何恢复动做,而且已经从文件中读取到所须要的信息,所以不用终止正在进行的操做。
关于finally须要注意的几点:
1)、finally中的代码老是会被执行,除非在执行try或者catch语句时虚拟机退出(System.exit(1))。
2)、finally块能够作一些资源清理工做,如关闭文件、关闭游标等操做。
3)、finally块不是必须的。
另外,若是在try和finally块中都执行了return语句,最终返回的将是finally中的return值。
3.2 异常链
经常想要在捕获一个异常后抛出另一个异常,而且但愿把原始异常信息保存下来,这就是异常链。在JDK1.4之后,Throwable子类在构造器 中能够接受一个cause对象做为参数,表示原始异常,经过这样把原始异常传递给新的异常,使得即便在当前位置建立并抛出了新的异常,也能经过这个异常链 追踪到异常最初发生的位置。
但在Throwable子类中,只有Error, Exception, RuntimeException三类异常类提供了带cause参数的构造器,其它类型的异常则须要经过initCause()方法。例如定义了CustomException类,能够这样使用:
CustomException cmex = new CustomException(); cmex.initCause(new NullPointerException); throw cmex;
这样一来,CustomException继承自Exception或RuntimeException,就属于自定义异常了。
通常来讲,自定义异常的做用有如下情形:
1)、将检查型异常转换为非检查型异常。
2)、在产生异常时封装上下文信息、定义异常码、收集环境对象,有利于信息的传递。
四、异常使用指南
1)、在知道该如何处理的状况下才捕获异常。
2)、自定义异常类型,用以封装全部的检查型异常。
3)、在程序的边界进行异常捕获。如服务端相应客户端的请求,在出口处catch内部有可能产生的异常,并统一throw一个封装过的异常给客户端,省得暴露服务端敏感信息。
4)、只针对异常的状况才使用异常。不要在全部的代码中习惯性地使用try-catch,由于这会影响性能。
5)、抛出与抽象相对的异常。若是方法抛出的异常与它执行的任务没有明显的联系,这种情形会令人不知所措。为了不这个问题,更高层的实现应该捕获 低层的异常,同时抛出能够按照高层抽象进行解释的异常,这种作法被称为异常转译(exception translation),以下:
try{ // use lower-level abstraction to do our bidding } catch(LowerLevelException ex){ throw new HigherLevelException(...); }
另一种特殊的异常转译称为异常链,上面已做描述。若是低层的异常对于调试致使高层异常的问题很是有帮助,使用异常链就很合适。高层的异常提供访问方法(Throwable.getCause)来得到低层的异常。
6)、每一个方法抛出的异常要有文档描述。利用Javadoc的@throws标记,记录抛出每一个异常的条件。若是一个方法可能抛出多个异常,不要使 用这些异常类的某个超类。如不要声明一个方法“throws Exception”或“throws Throwable”,这将没有任何指导信息。
欢迎加入学习交流群569772982,你们一块儿学习交流。