zoukankan      html  css  js  c++  java
  • 异常处理

    java类的继承体系

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

      实际上,进行异常捕获时不仅应该把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块里的资源回收!");
            }
        }
    }

    输出:

    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块里的任何代码。

      如上所示,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语句在该语句结束时自动关闭这些资源。

     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());
            }
        }
    }
  • 相关阅读:
    多线程ExecutorService 的理解与使用
    MySql索引
    HttpURLConnection和HttpClient使用
    httpclient调用接口
    几个linux命令
    面试之自定义字符串操作
    C和C++中struct的区别
    如何根据端口号查看占用进程
    linux和window如何发布服务
    MYSQL中GROUP_CONCAT和CONCAT函数配合使用
  • 原文地址:https://www.cnblogs.com/qiaoshanzi/p/5771162.html
Copyright © 2011-2022 走看看