异常:异常指的是在程序运行过程当中发生的异常事件,一般是由外部问题(如硬件错误、输入错误)所致使的。java
异常情形:异常情形是阻止当前方法或做用域继续执行的问题,异常情形特色是在当前环境没法得到必要信息来解决问题。数组
抛出异常:抛出异常是指面对异常情形,从当前环境跳出,把问题交给上一级环境。spa
捕获异常:若是某方法内部抛出了异常或方法内部调用的其余人方法抛出了异常,这个方法将在抛出异常的过程当中结束。当不但愿该方法就此结束时,可在方法内设置一个特殊块来捕获异常并交由异常处理程序进行处理。设计
异常处理程序:抛出的异常必须在某处获得处理,这个地点就是异常处理程序,针对于每个捕获的异常,须要有相应的处理程序。指针
Throwable类被用来表示任何能够做为异常被抛出的类。它分为两种类型:Error表示编译时和系统错误;Exception是能够被抛出的基本类型。在Java类库中,用户方法和运行时故障都有可能抛出Exception,设计程序时须要关注它。code
Exception类分为RuntimeExceprion--程序错误致使的异常;其余异常--例如I/O错误。对象
RuntimeException情形包括:blog
1)错误类型转换继承
2)数组访问越界事件
3)访问null指针
其余异常情形包括:
1)试图在文件尾部后面读取数据
2)试图打开一个不存在的文件
3)试图根据给定的字符串查找Class对象,而该字符表示的类不存在。
不受检查异常:运行时异常会自动被Java虚拟机抛出,因此没必要在异常说明中罗列出来,这些异常被称为不受检查异常,即从RuntimeException继承的异常。
受检查异常:而Exception下的除RuntimeException其余异常都被称为受检查异常,编译器会检查此类异常,若是不将异常捕获或抛出,将不能经过编译。
对于对象引用,使用对象引用调用其方法前,会对引用进行检查,能够建立一个表明错误信息的对象,并将其从当前环境中抛出,相似于:
if(t == null) throw new NullPointException();
在堆上会建立一个异常对象,以后当前执行路径被终止,从当前环境弹出对异常对象的引用,异常处理程序接管程序。
异常对象会传递给throw,故从效果看,能够将异常处理看作一种不一样的返回机制。
String readData(Scanner in) throws EOFException { //code while(//code) { if(in.hasNext()) //EOF encountered { if(n < len) throw new EOFException(); } //code } return s; }
throws是可能抛出的异常类的什么声明,写在方法参数列表后,如有多个类,则用逗号隔开。当某个方法可能会抛出某种异常时,用throws 声明可能抛出的异常,而后交给上层调用它的方法程序处理。
throw抛出的是对象,写在方法体里面。
使用try/catch来捕获异常,若是在try语句块中任何代码抛出了在catch语句中说明的异常类,那么程序将1)跳过try语句块的剩余代码 2)执行catch语句块的代码
try{ //code that might generate exception }catch(TypeOfException e){ //Handle }
能够用多个catch语句来捕获多个异常
try{ //code that might generate exception }catch(TypeOfException xxx){ //Handle }catch(Exception yyy){ //Handle }catch(Exception zzz){ //Handle }
异常对象有多个方法能够获取详细信息:getMessage(),getLocalizedMessage(),toString(),printStackTrace()等。
public class ExceptionMethods { public static void main(String[] args) { try { throw new Exception("myException"); }catch (Exception e){ System.out.println("Caught Exception"); System.out.println("getMessage" + e.getMessage() ); System.out.println("getLocalizeMessage" + e.getLocalizedMessage()); System.out.println("toString" + e.toString()); System.out.println("getStacktrace"); e.printStackTrace(System.out); } } }
结果:
Caught Exception
getMessagemyException
getLocalizeMessagemyException
toStringjava.lang.Exception: myException
getStacktrace
java.lang.Exception: myException
at ExceptionMethods.main(ExceptionMethods.java:6)
catch子句中能够再次抛出异常,再次抛出异常会将异常交给上一级的异常处理程序,同一个try块的后续catch子句将被忽略,该异常对象信息获得保存。
再次抛出异常的目的通常是为了改变异常类型。
try{ access the database }catch(SQLException e){ throw new servletException("databaseError" + e.getMessage()); }
然而,这种方法抛出的异常,将覆盖原异常的细节,而须要保留原异常的细节并仍然抛出新异常,须要使用initCause()将异常缘由描述为原异常,经过将原异常传递给新异常,即便在当前位置建立并抛出了新异常,也能经过异常链追踪到异常最初发生的位置。
try{ access the database }catch(SQLException e){ throwable se = new servletException("databaseError"); se.initCause(e); throw se; }
以后能够用throwable e = se.getCause()获取原始异常.
当代码抛出一个异常时, 就会终止方法中剩余代码的处理,并退出这个方法的执行。若是方法得到了一些本地资源,而且只有这个方法本身知道,又若是这些资源在退出方法以前必须被回收,那么就会产生资源回收问题。一种解决方案是捕获并从新抛出全部的异常。可是,这种解决方案比较乏味,这是由于须要在两个地方清除所分配的资源。一个在正常的代码中;另外一个在异常代码中。Java提供了finally子句解决这个问题。
不论是否有异常被捕获,finally子句中的代码都会被执行,能够在finally子句中进行资源清理。
如下例子分析程序可能执行状况:
1)代码没有异常,程序按照1,2,5,6顺序执行
2)try子句中抛出io异常,catch子句中没有再次抛出异常,程序按照1,3,4,5,6顺序执行
3)try子句中抛出io异常,catch子句中再次抛出异常,程序按照1,3,5,6,顺序执行
4)try子句抛出catch子句中没有捕获的异常,程序按照1,5,6顺序执行
InputStream in = new FileInputStream(...) try { //1 code that might throw exception //2 } catch(IOException e) { //3 show error message //4 } finally { //5 in.close(); } //6
事实上,资源清理过程当中,也可能出现异常,可使用带资源的try语句解决问题。
带资源的try语句最简形式以下,try块退出时,会自动执行res.close()
try (Resource res = . . .) { work with res }
以下示例,这个块不管正常或异常,结束后都会调用in.close()
try (Scanner in = new Scanner(new FileInputStream("xxx")) , "UTF-8") { while (in.hasNextO) System.out .println(in.next ()) ; }