异常处理

java类的继承体系

  Error错误,通常是指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态连接失败等,这种错误没法恢复或不可捕获,将致使应用程序中断。一般应用程序没法处理这些错误,所以应用程序不该该试图使用catch块来捕获Error对象。在定义该方法时,也无须在其throws子句中声明该方法可能抛出Error及其任何子类。java

  实际上,进行异常捕获时不只应该把Exception类对应的catch块放在最后,并且全部父类异常的catch块都应该排在子类异常catch块的后面(简称:先处理小异常,再处理大异常),不然将出现编译错误。数据库

使用finally回收资源

有时候程序在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也能够包含异常处理。对象

自动关闭资源的try语句

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

 checked异常和unchecked异常

  一般,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代码在某处所抛出的异常。简单地说,异常老是先被抛出,后被捕捉的。

catch和throw同时使用

  当出现一个状况时,单靠某个方法没法彻底处理该异常,必须由几个方法协做才可彻底处理该异常。也就是说,在异常出现的当前方法中,程序只对异常进行部分处理,还有些处理须要在该方法的调用者中才能完成,因此应该再次抛出异常,让该方法的调用者也能捕获异常。

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());
        }
    }
}
相关文章
相关标签/搜索