代码的世界和现实世界同样,不会一路顺风,起码不会像咱们想象中的那么顺利。写代码的是人,人的思惟存在局限性,这种局限性,体如今代码中,就是漏洞。假若一段程序在生产环境中崩溃,势必让人十分恼火。这种让人头大的状况就是异常的一种。html
Java 是这样定义异常的:java
异常指的是,那些在程序运行过程当中,中断正常的指令流程的事件。
实际上,异常还会在如下场景中发生:程序员
而咱们并不但愿程序由于上述状况挂掉,而是但愿程序可以在遇到异常时,巧妙地处理以后,继续运行下去。oracle
所幸,Java 提供了一套机制,用于在程序程序出错(出现异常)时,进行:编码
亦即:异常处理机制。顾名思义,该机制用于对程序运行中不正常的状况进行处理。
简单来讲,Java 中的异常处理是:当异常发生时,运行时系统逆着方法的调用栈(call stack)去寻找可以处理这种异常的东西。spa
以一个把字符串转换成整数的方法为例:设计
public Integer stringToNumber(String strToFormat){ Integer targetNum; try{ targetNum = new Integer(strToFormat); }catch(NumberFormatException e){ targetNum = DEFAULT_NUM; } return targetNum; }
在上述代码中,当 strToFormat 不能转化成一个整形数时,就转化成一个默认的值。NumberFormatException
发生时,方法当即终止。控制权被交由 catch 代码块,也就是异常处理器(exception hanlder)。代码虽然简单,却包含了 Java 异常处理的通常步骤。code
在 Java 中,全部的异常派生于 Throwable 接口。这些异常,又被分为 Error 和 Exception。这两类异常,又衍生了一些子类。下面的图片,描述了 Java 的异常体系图:orm
不过,咱们应当把精力放在 RuntimeException 上,由于“全部的运行时异常,都是程序员的问题”。这类异常,又被叫作未检查异常,一般交由 JVM 处理。相对应的,那些咱们知道可能会出现问题、,被叫作已检查的异常。这类异常须要开发者手动向上级抛出,直到 JVM 级别,或者在调用方法时使用 try-catch
处理。htm
通常来讲,在写一个方法时,要尽量声明全部已检查异常,经过内部逻辑控制,避免未检查(运行时)异常。
在编码过程当中,若是方法的检查异常被精心设计,那么咱们只管抛出异常便可。可是,一旦调用方法的地方没有对这种可能出现的异常进行处理,那么程序就会终止。因此,要对异常进行捕获操做,正如以前的字符串转数字的方法同样。
根据经验,程序中应该捕获那些知道如何处理的异常,把“职责”外的异常,交给方法的调用者去处理。下面是一个异常捕获流程的示例代码:
modifier returnType someMethod(type1 param1, type2 param2) throws Exception1, Exceptio2{ try{ ① // 某些操做 return returnType value; }catch(Exceptionx | Exceptiony e){ ② // 处理异常 }catch(Excpetion1 e1){ ③ throw new Excption1(e1); }catch(Exception e2){ ④ throw e2; }finally{ ⑤ // 一些操做 return returnType mockValue; } }
在上述代码中,① 中进行操做,捕获了 Exeptionx 或者 Exceptiony 时,② 进行异常处理;捕获了 Exception1 时, ③ 把该异常包装;捕获了 Exception 2 时,④ 直接抛出异常;不管有无异常发生,⑤ 都会执行。
上面的代码还有一个问题,就是 finally 代码中包含返回值。有如下规则:
try
块处理的尽可能用一个,而后按层次捕获异常,下面的代码是被建议的:try{ // 某些操做 }catch(SomeException1 e1){ // 异常 1 的处理 }catch(SomeException2 e2){ // 异常 2 的处理 }
NumberFormatException
转化成自定义的异常