zoukankan      html  css  js  c++  java
  • 【Java】 异常

    异常分类

    异常层次结构

    1. 所有的异常都是由Throwable继承而来,但在下一层理解分解为两个类Error和Exception。
    2. Error类层次结构描述了Java运行时系统的内部错误和资源耗尽错误。应用程序不应该跑出这种类型的对象。如果出现了这样的内部错误,除了通告给用户,并尽力使程序安全地终止之外,再也无能为力。
    3. 在设计Java程序时,需要关注Exception层次,这个层次结构又分解为两个分支:一个分支派生于RuntimeException;另一个分支包含其他异常。划分两个分支的规则是:由程序错误导致的异常属于RuntimeException;而程序本身没有问题,但由于I/O错误这类问题导致的异常属于其他异常。
    4. 派生于RuntimeException的异常包含下面几种情况:
    • 错误的派生类型
    • 数组访问越界
    • 访问空指针
      不是派生于RuntimeException的异常包括:
    • 试图在文件尾部后面读取数据
    • 试图打开一个不存在的文件
    • 试图根据给定的字符串查找Class对象,而这个字符串表示的类并不存在。
    1. Java语言规范将派生于Error类或RuntimeException类的所有异常称为未检查(unchecked)异常,所有其他的异常称为已检查(checked)异常。

    声明已检查的异常

    方法应该在其首部声明所有可能出现抛出的异常。这样可以从首部反映出这个方法可能抛出哪类已检查异常。

    public FileInputStream(String name) throws FileNotFoundException
    
    1. 在编写自己的方法时,不必将所有可能抛出的异常都进行声明。置于什么时候需要在方法中用throws子句声明异常,什么异常必须使用throws子句声明,需要记住在下面4种情况时应该抛出异常:
      1)调用一个抛出已检查异常的方法,例如,FileInputStream构造器。
      2)程序运行过程中发现错误,并且利用throw语句抛出一个已检查异常
      3)程序出现错误,例如,a[-1]=0会抛出一个ArrayIndexOutOfBoundsException这样的未检查异常
      4)Java虚拟机和运行时库出现的内部错误
      如果出现了前两种情况之一,则必须告诉调用这个方法的程序员有可能抛出异常。因为任何一个抛出异常的方法都有可能是一个死亡陷阱。如果没有处理器捕获这个异常,当前执行的线程就会结束。
    2. 对于那些可能被他人使用的Java方法,应该根据异常规范(Exception specification),在方法的首部声明这个方法可能抛出的异常。
    class MyAnimation {
        public Image loadImage(String s) throws IOException {
            ...
        }
    }
    

    如果一个方法有可能抛出多个已检查异常,那么就必须在方法的首部列出所有的异常类。每个异常类之间用逗号隔。如:

    class MyAnimation {
        poblic Image loadImage(String s) throws FileNotFoundException, EOFException {
            ...
        }
    }
    

    但是,不需要声明Java的内部错误,即从Error继承的错误。任何程序代码都具有抛出那些异常的潜能,而我们对其没有任何控制能力。
    同样,也不应该声明从RuntimeException继承的那些未检查异常。

    class MyAnimation{
        void drawImage(int i) throws ArrayIndexOutOfBoundsException { //bad style
            ...
        }
    }
    

    这些运行时错误完全在我们的控制之下。如果特别关注数组下标引发的错误,就应该讲更多的时间花费在修正程序中的错误上,而不是说明这些错误发生的可能性上。
    总之,一个方法必须声明所有可能抛出的已检查异常,而未检查异常要么不可控制(Error),要么就应该避免发生(RuntimeException)。如果方法没有声明所有可能发生的已检查异常,编译器就会给出一个错误消息。

    捕获异常

    如果某个异常发生的时候没有进行捕获,那程序就会终止执行,并在控制台上打印出异常信息,其中包括异常的类型和堆栈的内容。要想捕获一个异常,必须设置try/catch语句块。最简单的try语句块如下所示:

    try {
        code
        more code
        more code
    } catch (ExceptionType e) {
        handler for this type
    }
    

    如果在try语句块中的任何代码抛出了一个在catch自娱中说明的异常类,那么
    1)程序将跳过try语句块的其余代码。
    2)程序将执行catch字句中的处理器代码。
    如果在try语句块中的代码没有抛出任何异常,那么程序将跳过catch子句。
    如果方法中的任何代码抛出了一个在catch子句中没有声明的异常类型,那么这个方法就会立刻退出。
    通常捕获哪些知道如何处理的异常,而将那些不知道如何处理的异常继续进行传递。如果想传递一个异常,就必须在方法的首部添加一个throws说明符,以便告知调用者这个方法可能会抛出异常。

    捕获多个异常

    在一个try语句块中可以捕获多个异常类型,并对不同类型的异常做出不同的处理。可以按照下列方式为每个异常类型使用一个单独的catch子句:

    try {
        code that might throw exceptions
    } catch (FileNotFoundException e) {
        emergency action for missing files
    } catch (UnknownHostException e) {
        emergency action for unknown hosts
    } catch (IOException e) {
        emergency action for all other I/O problems
    }
    

    在Java SE7中,同一个catch子句中可以捕获多个异常类型。例如,假设对应缺少文件和异常未知主机异常的动作是一样的,就可以合并catch子句:

    try {
        code that might throw exception
    } catch (FileNotFoundException  | UnknownHostException e) {
        emergency action for missing files and unknown hosts
    } catch (IOException e) {
        emergency action for all other I/O problems
    }
    

    只有当捕获的异常类型彼此之间不存在子类关系时才需要这个特性。

    捕获所有异常

    可以只写一个异常处理程序来捕获所有类型的异常。通过捕获异常类型的基类Exception,就可以做到这一点(事实上还有其他的基类,但Exception是同编程活动相关的基类):

    catch(Exception e) {
        System.out.println("Caught an exception");
    

    这将捕获所有异常,所以最好把它放在处理程序表的末尾,以防它抢在其他处理程序之前就把异常捕获了。

    再次抛出异常与异常链

    在catch子句中可以抛出一个异常,这样做的目的是改变异常的类型。如果开发了一个供其他程序员使用的子系统,那么,用于表示子系统故障的异常类型可能会产生多种解释。ServletException就是这样一个异常类型的例子。执行servlet的代码可能不想知道发射给你错误的细节原因,但希望明确地知道servlet是否有问题。
    下满给出了捕获异常并将它再次抛出的基本方法:

    try {
        access the database;
    } catch (SQLException e) {
        throw new ServletException("..") 
    }
    

    finally子句

    不管是否有异常被捕获,finally子句中的代码都被执行

  • 相关阅读:
    吃了很多杏仁,干果的祸
    persistent.xml hibernate 利用sql script 自定义生成 table 表
    JSF dataTable 添加列 动态创建数据表 列
    java 和 mysql 获取周 星期 的第一天 最后一天 或者 月的 日期(字符串转日期,日期转字符串,日期加减)
    JSF JQUERY 使用datepicker
    JPA mysql wildfly jboss 存储时乱码
    JPA事务总结
    这样吃饭,其实是在喂养身体里的“癌细胞”
    Mysql 列转行统计查询 、行转列统计查询
    mysql 生成排名字段
  • 原文地址:https://www.cnblogs.com/vincently/p/6259678.html
Copyright © 2011-2022 走看看