Error错误,通常是指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态连接失败等,这种错误没法恢复或不可捕获,将致使应用程序中断。一般应用程序没法处理这些错误,所以应用程序不该该试图使用catch块来捕获Error对象。在定义该方法时,也无须在其throws子句中声明该方法可能抛出Error及其任何子类。java
实际上,进行异常捕获时不只应该把Exception类对应的catch块放在最后,并且全部父类异常的catch块都应该排在子类异常catch块的后面(简称:先处理小异常,再处理大异常),不然将出现编译错误。数据库
有时候程序在try块中打开一些物理资源(例如数据库链接、网络链接和磁盘文件等)这些物理资源都必须显示回收。java垃圾回收机制不会回收任何物理资源,垃圾回收机制只能回收堆内存中对象所占用的内存。网络
import java.io.*; public class FinallyTest { public static void main(String[] args) { FileInputStream fis = null; try { fis = new FileInputStream("b.txt"); } catch (IOException ioe) { System.out.println(ioe.getMessage()); // return语句强制方法返回 return ; // ① // 使用exit来退出虚拟机 // System.exit(1); // ② } finally { // 关闭磁盘文件,回收资源 if (fis != null) { try { fis.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } System.out.println("执行finally块里的资源回收!"); } } }
输出:spa
b.txt (系统找不到指定的文件。)
执行finally块里的资源回收!
虽然return语句也可强制方法结束,可是必定会先执行finally块里的代码。若是把①注释掉,取消②的注释,那么不会执行finally块里的代码。也就是说,除非在try块、catch块中调用了退出虚拟机的方法,不然无论在try块、catch块中执行怎样的代码,出现怎样的状况,异常处理的finally块总会被执行。指针
一般状况下,不要在finally块中使用如return或throw等致使方法终止的语句,这将会致使try块、catch块中的return、throw语句失效。当java程序执行try块、catch块时遇到了return或throw语句,这两个语句都会致使该方法当即结束,可是系统执行这两个语句并不会结束该方法,而是去寻找该异常处理流程中是否包含finally块,若是没有finally快块,程序当即执行return或throw语句,方法终止;若是有finally块,程序当即开始执行finally块——只有当finally块执行完成后,系统才会再次跳回来执行try块、catch块里的return或throw语句,若是finally块里也使用了return或throw等致使方法终止的语句,finally已经终止了方法,系统将不会跳回去执行try块、catch块里的任何代码。code
如上所示,finally也能够包含异常处理。对象
import java.io.*; public class AutoCloseTest { public static void main(String[] args) throws IOException { try ( // 声明、初始化两个可关闭的资源 // try语句会自动关闭这两个资源。 BufferedReader br = new BufferedReader(new FileReader("AutoCloseTest.java")); PrintStream ps = new PrintStream(new FileOutputStream("a.txt"))) { // 使用两个资源 System.out.println(br.readLine()); ps.println("庄生晓梦迷蝴蝶"); } } }
java7加强了try语句的功能,它容许在try关键字后紧跟一对圆括号,圆括号能够声明、初始化一个或多个资源,此处的资源指的是那些必须在程序结束时显式关闭的资源(好比数据库链接、网络链接),try语句在该语句结束时自动关闭这些资源。blog
一般,Java的异常(包括Exception和Error)分为可查的异常(checked exceptions)和不可查的异常(unchecked exceptions)。
可查异常(编译器要求必须处置的异常):正确的程序在运行中,很容易出现的、情理可容的异常情况。可查异常虽然是异常情况,但在必定程度上它的发生是能够预计的,并且一旦发生这种异常情况,就必须采起某种方式进行处理。继承
除了RuntimeException及其子类之外,其余的Exception类及其子类都属于可查异常。这种异常的特色是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,不然编译不会经过。内存
不可查异常(编译器不要求强制处置的异常):包括运行时异常(RuntimeException与其子类)和错误(Error)。
Exception 这种异常分两大类运行时异常和非运行时异常(编译异常)。程序中应当尽量去处理这些异常。
运行时异常:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中能够选择捕获处理,也能够不处理。这些异常通常是由程序逻辑错误引发的,程序应该从逻辑角度尽量避免这类异常的发生。
运行时异常的特色是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即便没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译经过。
非运行时异常 (编译异常):是RuntimeException之外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,若是不处理,程序就不能编译经过。如IOException、SQLException等以及用户自定义的Exception异常,通常状况下不自定义检查异常。
因为运行时异常的不可查性,为了更合理、更容易地实现应用程序,Java规定,运行时异常将由Java运行时系统自动抛出,容许应用程序忽略运行时异常。
对于方法运行中可能出现的Error,当运行方法不欲捕捉时,Java容许该方法不作任何抛出声明。由于,大多数Error异常属于永远不能被容许发生的情况,也属于合理的应用程序不应捕捉的异常。
对于全部的可查异常,Java规定:一个方法必须捕捉,或者声明抛出方法以外。也就是说,当一个方法选择不捕捉可查异常时,它必须声明将抛出异常。
可以捕捉异常的方法,须要提供相符类型的异常处理器。所捕捉的异常,多是因为自身语句所引起并抛出的异常,也多是由某个调用的方法或者Java运行时 系统等抛出的异常。也就是说,一个方法所能捕捉的异常,必定是Java代码在某处所抛出的异常。简单地说,异常老是先被抛出,后被捕捉的。
当出现一个状况时,单靠某个方法没法彻底处理该异常,必须由几个方法协做才可彻底处理该异常。也就是说,在异常出现的当前方法中,程序只对异常进行部分处理,还有些处理须要在该方法的调用者中才能完成,因此应该再次抛出异常,让该方法的调用者也能捕获异常。
import exception.AuctionException; public class AuctionTest { private double initPrice = 30.0; // 由于该方法中显式抛出了AuctionException异常, // 因此此处须要声明抛出AuctionException异常 public void bid(String bidPrice) throws AuctionException { double d = 0.0; try { d = Double.parseDouble(bidPrice); } catch (Exception e) { // 此处完成本方法中能够对异常执行的修复处理, // 此处仅仅是在控制台打印异常跟踪栈信息。 e.printStackTrace(); // 再次抛出自定义异常 throw new AuctionException("竞拍价必须是数值," + "不能包含其余字符!"); } if (initPrice > d) { throw new AuctionException("竞拍价比起拍价低," + "不容许竞拍!"); } initPrice = d; } public static void main(String[] args) { AuctionTest at = new AuctionTest(); try { at.bid("df"); } catch (AuctionException ae) { // 再次捕捉到bid方法中的异常。并对该异常进行处理 System.err.println(ae.getMessage()); } } }