• 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();
  • 相关阅读:
    JVM收藏的文章
    【转】Mysql相关子查询&&MySQL获取分组后的TOP N记录
    【转】JVM--内存区域划分
    【转】Nginx location写法
    【转】Dockerfile
    CORS web.xml 里配置
    分布式事务
    maven+dubbo+SpringMVC 项目搭建
    dubbo 报错
    多重背包问题:POJ2392
  • 原文地址:https://www.cnblogs.com/pzy4447/p/4727848.html
Copyright © 2020-2023  润新知