资讯专栏INFORMATION COLUMN

【译】Java异常处理策略

cartoon / 2870人阅读

摘要:指示该错误是否严重,此属性会在该异常根据错误的上下文遍历堆栈时进行更新,严重性会指示异常捕获代码是应该停止程序还是该继续处理。引发异常在检测到错误并无法从中恢复时,异常将向上传播到调用堆栈,直到到达处理它的某个块。

翻译:疯狂的技术宅
原文标题:Exception handling strategy
原文链接:http://programmergate.com/exc...
本文首发微信公众号:充实的脑洞

在本文中,我们介绍了在OOP应用中处理异常的常见策略,这些策略符合最佳的异常处理技术,可以在任何应用中使用。

1. 概述

下图提供了策略概述,它展示了从检测阶段到处理阶段的异常处理流程。该图需要从下往上进行阅读:

Error detection: 在策略的底部是错误检测,这是发生异常的地方,它要么由程序进行检测,要么由一些外部调用引发。

Local exception handling: 在第二级是本地异常处理,检测错误的类尝试在本地处理异常,例如:将请求发送到备份服务器,或等待X秒后再次尝试等...如果异常无法恢复,则将其传播到较高级别。

Propagate exception to higher levels: 当本地错误处理不起作用时,该类收集诊断信息,再现和报告错误所需的所有信息,然后将该异常传到栈中。 如果检测到的异常不是低级别依赖(取决于低级别实现),那么它将被抛出,否则将被转换为自定义异常,以实现组件之间的解耦。

Keep propagating if nothing to do with the exception: 较高级别的类将会继续将异常传到栈中, 只要它们与异常无关。同时关闭在传递路径的所有资源(例如文件、网络连接、释放分配的缓冲区等),并添加相关的上下文信息, 这将有助于确定错误的原因和严重性。

Handle exception:在这个阶段,异常会到达一个负责处理它的类,异常所携带的所有错误信息都记录在此,并且根据异常的严重性,该类可以处理异常或者结束程序。

2. 自定义异常模板

实现异常处理策略时要做的第一件事就是,为程序的每个组件创建自定义异常,自定义异常如下所示:

public class ComponentException extends Exception {
    private static final long serialVersionUID = 1L;
    private int errorCode;
    private String errorDescription;
    private boolean isSevere;
 
    public ComponentException() {
        super();
    }
 
    public ComponentException(Exception ex) {
        super(ex);
    }
 
    public int getErrorCode() {
        return errorCode;
    }
 
    public void setErrorCode(int errorCode) {
        this.errorCode = errorCode;
    }
 
    public String getErrorDescription() {
        return errorDescription;
    }
 
    public void setErrorDescription(String errorDescription) {
        this.errorDescription = errorDescription;
    }
 
    public boolean isSevere() {
        return isSevere;
    }
 
    public void setSevere(boolean isSevere) {
        this.isSevere = isSevere;
    }
 
}

以下描述了ComponentException类的属性:

errorCode:识别此错误的唯一代码,errorCode告诉我们那里出错了,程序的所有错误代码应在静态类中进行预定义。该属性指示异常捕获代码应该怎样处理这个错误。

errorDescription: 对错误的描述,描述了用户、程序操作人员和可能的程序开发人员所需的一切必要的细节,可以使他们了解到底发生了什么错误。

isSevere: 指示该错误是否严重,此属性会在该异常根据错误的上下文遍历堆栈时进行更新,严重性会指示异常捕获代码是应该停止程序还是该继续处理。

3.引发异常

在检测到错误并无法从中恢复时,异常将向上传播到调用堆栈,直到到达处理它的某个 try-catch块。该异常可以按原样传递,也可转换为自定义异常。

3.1 抛出异常

如果异常不依赖于定期更改的低级实现或动态实现,那么你只需关闭打开的资源,并把异常积蓄传到调用栈而不去捕获它。下面是一个例子:

public void doSomething() throws SomeException {
    try{
        doSomethingThatCanThrowException();
    } finally {
       //close the opened resources
    }
}
3.2 抛出自定义异常

当捕获的异常取决于低级别或动态实现时,它会被转换为一个特定的异常,然后重新启动调用堆栈。 下面是一个例子:

public Student readStudent(String id) throws SomeException {
    try
    {
        // Some code which reads a student from oracle database 
    }
    catch(SQLException ex)
    {
        DataAccessException dataAccessException = new DataAccessException(ex);
        dataAccessException.setErrorCode(101); // we assume this code denotes student not found
        dataAccessException.setErrorMessage("An error occurred while reading " + 
        "student with id: " + id + " from database");
        dataAccessException.setSeverity(false);
        throw dataAccessException;
    }
}

只要它还没有到达能够处理它的类,异常就会继续传播。

P.S:强烈建议在异常传播到堆栈时更新异常的严重性,无论是异常被继续抛出,还是转换为自定义异常。

4. 捕获异常

在程序中,你需要捕获并响应来抛出异常,通常你需要在调用层次的顶部执行此操作。

捕获异常时首先要做的是记录它,通常我更喜欢使用printStackTrace(),之后的处理过程取决于异常的严重性:

如果严重,则通知开发人员和程序操作人员,并且结束程序。

如果不严重,则根据错误代码完成处理。通常有两种可能性,可以静默地从异常中恢复,或者通知最终用户并停止当前进程。

下面是一个例子:

try{
    startTheWholeThing();
} catch(MyAppException e) {
    e.printStackTrace();
    if(e.isSevere())
    {
        notifyNonUsers(e);
        // Halt the system gracefully        
    }
    else
    {
        if(e.getErrorCode() == 100)
        {
            // do some silent recovery logic
        }
        else
        {
            notifyUsers(e);
        }
    }
}

以上是我在程序中处理异常时所遵循的策略,希望你能喜欢。

关注微信公众号:充实的脑洞, 一个技术宅的保留地

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/67719.html

相关文章

  • [] Java 中最常见的 5 个错误

    摘要:近日,在上列举了开发中常见的个错误,与君共免。在多线程中并发修改集合内容是非常常见的,因此需要使用并发编程中常用的方法进行处理,例如同步锁对于并发修改采用特殊的集合等等。在单线程和多线程情况下解决这个问题有微小的差别。 在编程时,开发者经常会遭遇各式各样莫名错误。近日,Sushil Das 在 Geek On Java上列举了 Java 开发中常见的 5 个错误,与君共「免」。 原文...

    chemzqm 评论0 收藏0
  • Java中生产者与消费者问题的演变

    摘要:生产者消费者问题是一个典型的多进程同步问题。生产者线程开始产生新的元素并将它们存储在缓冲区。否则,生产者线程将会在缓冲区创建一个新元素然后通知消费者。我们建立一个线程池,它将收到两个任务,生产者和消费者的任务。 原文链接:https://dzone.com/articles/th... 作者:Ioan Tinca 译者:liumapp 想要了解更多关于Java生产者消费者问题的演变吗?...

    王伟廷 评论0 收藏0
  • Java 核心内容相关面试题

    摘要:能否声明一个内容为空的接口可以。能否将接口声明为不允许,这样做会导致编译错误。当异常没有被捕获时,会发生什么当前线程所在的线程组会执行一个叫的方法,最后程序会异常退出。非静态内部类可以使用哪些修饰符非静态内部类可以使用或修饰符。 原文地址 http://www.instanceofjava.com/2014/12/core-java-interview-questions.html 1...

    sunny5541 评论0 收藏0
  • How to handle Null Pointer Exception(

    摘要:我们应该考虑使用字符串常量调用方法来代替使用对象调用该方法。然而如果我们通过字符串常量来调用方法,执行流程会正常进行检查方法的参数在执行方法的方法体之前,务必对方法的参数进行值检查。 原文地址作者 Sotirios-Efstathios (Stathis) Maneas译者 smallcloverThanks for your watching! java.lang.NullPoine...

    MRZYD 评论0 收藏0
  • 】RabbitMQ系列(二)-Work模式

    摘要:每个消费者会得到平均数量的。为了确保不会丢失,采用确认机制。如果中断退出了关闭了,关闭了,或是连接丢失了而没有发送,会认为该消息没有完整的执行,会将该消息重新入队。该消息会被发送给其他的。当消费者中断退出,会重新分派。 Work模式 原文地址showImg(https://segmentfault.com/img/bVbqlXr?w=694&h=252); 在第一章中,我们写了通过一个...

    lcodecorex 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<