zoukankan      html  css  js  c++  java
  • Java-错误处理机制学习(一)异常处理

    注意:本文介绍Java中的异常处理理论知识及相关语法结构,对于实际应用来说是万万不够的。关于如何高效地使用异常,请查看Java-高效地使用Exception-实践

    异常处理的思想是,当应用程序处于异常时,它可以声明这种异常;然后这种异常将被捕获到并得到妥善地处理,从而避免出现严重后果。所谓异常,是值与程序的正常运行逻辑相违背的非正常事件,比如,读取文件内容时,文件不存在;或者说对数组进行操作时,数组下标越界等等。而用户登录时口令验证失败这种情况不能算作异常,因为它是验证程程序正常运行逻辑的一部分。

    一、异常层次结构与分类

    Java中的异常层次结构如下图所示:

     

    Error类层次结构描述了Java运行时系统的内部错误和资源耗尽错误。对于这种错误应用程序是无能为力的,因此应用程序不应该抛出这种类型的对象。

    Exception层次结构分解为两个分支:一支派生于RuntimeException,它表示由程序错误导致的异常。比如空指针、数组越界、错误的类型转换等等。

    另一个分支表示程序本身没有问题,出问题的是IO读写等外部操作,比如在文件尾部读取数据、打开了错误的URL等等。

    Java语言规范将派生干Error类或RuntimeException类的所有异常称为未检查(unchecked) 异常,所有其他的异常称为已检查(checked)异常。编译器将核査是否为所有的已检査异常提供了异常处理器。

    二、声明已检查异常

    根据异常规范,方法应该在首部声明所有可能抛出的异常。然而未检査异常要么不可控制(Error), 要么就应该避免发生(RuntimeException)。因此,规定方法必须对所有可能抛出的已检查异常进行声明,否则无法通过编译。

    那么,我们如何知道一个方法究竟存在哪些已检查异常呢?不用担心,编译器能够对我们进行提示。当方法调用了可能抛出异常的方法时,eclipse将自动告警,如下图:

     

    如果不按照提示进行修改则程序无法通过编译。

    三、抛出异常

    假设应用程序现在遇到了一个错误,需要抛出异常进行告警。那么,首先要确定异常的类型。Java已经事先定义好了许多Exception,常见的有IOException/SQLException等等,更多类型可以通过查阅API来确定。当然,我们也可以继承Exception然后创建自己的异常。接下来,创建异常实例,并使用throw关键字抛出异常。最后,在方法签名中声明抛出的异常类型。示例代码如下:

    public void read(File file) throws Exception{
            if(!file.exists()){
                Exception e = new FileNotFoundException();
                throw e;
            }
        }

    四、捕获异常

    异常的捕获、处理格式为:

    public void callRead(){
            try {
                //可能抛出异常的代码
                read(new File("filename1"));
                read(new File("filename2"));
            } catch (Exception e) {
                //异常处理代码
                e.printStackTrace();
            }
            finally{
                //无论如何需要执行的代码,比如释放资源    
            }
        }

    其中,try{}catch{}是必须的,finally是可选的。可能抛出异常的代码必须放在try{}中,否则异常无法被捕获;当捕获异常时,直接跳转到catch{}进行异常处理。比如说,读取filename1时捕获了异常,那么read(new File("filename2"));这局代码将被跳过不再执行。

    通常可能发生的异常不止一种,不建议都使用Exception对象进行捕获,因为它太通用,不能反映异常的具体类型。正确的做法是对不同的异常分别处理,即叠加多个catch块。

    程序中总有一些工作比如释放资源,无论发生异常与否都需要去做,那么可以放在finally{}中,它在catch{}完成后一定会执行。即使前面有return语句,也将在finally{}结束后才返回。

    五、再次抛出异常与异常链

    考虑这种情景:应用程序调用了server模块。模块内部可能会抛出加载资源出错、访问数据库出错等多种异常。对于应用程序来说,它只关心server模块是否发生异常,而不关系异常的细节。然而异常细节又不能丢失,它应该保存并由相应的人员去识别和处理。因此,捕获到底层异常时,我们需要根据它构造出一个更高级的异常并抛出,示例代码如下:

    public void convertExceptionTypeDemo() throws ServerException{
            try {
                //access the database
            } catch (SQLException e) {
                //异常处理代码
                throw new ServerException("database error" + e.getMessage());
            }
        }

    然而,Java中有更好的处理方法,就是将原始异常设置为新异常的诱饵,示例如下:

    public void chainedExceptionDemo() throws Throwable{
            try {
                //access the database
            } catch (SQLException e) {
                //异常处理代码
                Throwable serverException = new ServerException("database error");
                serverException.initCause(e);
                throw serverException;
            }
        }

    捕获到异常时,使用下列语句就能提出原始异常:

    Throwable exception = serverException.getCause();
  • 相关阅读:
    POJ 1659 Frogs' Neighborhood
    zoj 2913 Bus Pass(BFS)
    ZOJ 1008 Gnome Tetravex(DFS)
    POJ 1562 Oil Deposits (DFS)
    zoj 2165 Red and Black (DFs)poj 1979
    hdu 3954 Level up
    sgu 249 Matrix
    hdu 4417 Super Mario
    SPOJ (BNUOJ) LCM Sum
    hdu 2665 Kth number 划分树
  • 原文地址:https://www.cnblogs.com/pzy4447/p/4727848.html
Copyright © 2011-2022 走看看