Java异常处理之最佳实践

引言:

publicvoidconsumeAndForgetAllExceptions(){

    try{

        ...some code that throws exceptions

    } catch(Exception ex){

        ex.printStacktrace();

    }

}

采用上面这种方式处理异常时,catch代码段接管控制权,然后catch段之后代码继续执行,好像什么都没有发生。

 

publicvoidsomeMethod() throws Exception{

}

该方法内可能并不会抛出异常

总结:忽略异常或随意抛出异常是常见现象。

 

异常的本质 

广义的讲,抛出异常分三种不同的情况:

- 编程错误导致的异常:譬如NullPointerException和IllegalArgumentException),代码通常对编程错误没有什么对策。

- 客户端的错误导致的异常:试图违背制定的规则,例如读写文件流的关闭操作。

- 资源错误导致的异常:当获取资源错误时引发的异常。例如,系统内存不足,或者网络连接失败。

对于Java作为第一个使用checked exception的主流面向对象语言而言,高层必须catch或throw,若不能有效的处理异常的话,就会在API和代码之间造成负担。

publicList getAllAccounts() throws

    FileNotFoundException, SQLException{

    ...

}

Checked exception被诟病破坏封装性:getAllAccounts使得调用者必须处理这两个异常,但调用者不知道什么文件找不到&什么数据库语句失败,也不知道该提供什么文件系统或者数据库的事物层逻辑。这使得方法与调用者之间形成不恰当的紧耦合关系。

设计API的最佳实践

1. 根据客户端如何应对Exception决定使用checked exception还是unchecked exception

分析:若客户端可以采取行动恢复的建议采用checked exception

unchecked exception建议多用,因为它不强迫客户端必须处理,会扩散直到客户端想处理。建议采用Java定义好的异常类,更有利于代码的易读性。

2. 保持封装性

不要将针对某特定实现的checked exception用到更高的层次中去。

例如不要让SQLException扩散到逻辑层去,因为逻辑层是不需要知道SQLException。解决办法:a.客户端有相应应对措施时,转换SQLException为另一个checked exception

b.若客户端无法处理,转换SQLException为unchecked exception4. 将异常文档化你可以采用Javadoc’s @throws标签将你的API抛出的checked和unchecked
exception都文档化。

3. 不要忽略异常当一个API方法抛出checked exception时,如果对你没什么意义,直接转换成unchecked exception抛出,而不要仅仅用空的catch来忽略该异常。

处理示例:

之前代码:

publicvoiddataAccessCode(){

    try{

        ..some code that throws SQLException

    }catch(SQLException ex){

        ex.printStacktrace();

    }

}

上面catch段仅仅抑制住了异常,什么都没做,改成下面部分后,

publicvoiddataAccessCode(){

    try{

        ..some code that throws SQLException

    }catch(SQLException ex){

        thrownewRuntimeException(ex);

    }

}

此时,若发生SQLException异常,会抛给高层RuntimeException异常,使得当前线程挂起并爆出异常信息。此时逻辑层也不需要进行不必要的异常处理,尤其是逻辑层不知道怎么处理SQLException。

补充:若逻辑层打算采取恢复措施应对SQLException,那可以抛出自定义的checked exception。

4. 如果自定义的异常没有提供有用的信息的话,请不要创建它们。

a.当前异常发生时,给出一些相关的数据信息

publicclassDuplicateUsernameException

    extendsException {

    publicDuplicateUsernameException

        (Stringusername){....}

    publicStringrequestedUsername(){...}

    publicString[] availableNames(){...}

}

b.若不想获取详细信息,抛出标准异常也可以。

thrownewException("Username already taken");

注:抛出什么异常参见最佳实践第一点

 

 

使用异常的最佳实践

1. 记得释放资源

publicvoiddataAccessCode(){

    Connection conn = null;

    try{

        conn = getConnection();

        ..some code that throws SQLException

    }catch(SQLException ex){

        ex.printStacktrace();

    } finally{

        DBUtil.closeConnection(conn);

    }

}

classDBUtil{

    publicstaticvoidcloseConnection

        (Connection conn){

        try{

            conn.close();

        } catch(SQLException ex){

            logger.error("Cannot close connection");

            thrownewRuntimeException(ex);

        }

    }

}

DBUtil关闭连接工具类,最重要的部分在于finally,无论异常发不发生都会执行关闭连接操作,如果关闭发生异常会抛出一个RuntimeException。

 

2. 不要使用异常作控制流程之用

publicvoiduseExceptionsForFlowControl() {

    try{

        while(true) {

            increaseCount();

        }

    } catch(MaximumCountReachedException ex) {

    }

    //Continue execution

}

publicvoidincreaseCount()

    throws MaximumCountReachedException {

    if(count >= 5000)

        thrownewMaximumCountReachedException();

}

生成栈回溯的代价很昂贵,栈回溯的价值是在于调试,而不是流程控制中。

3 不要catch最高层次的exception

try{

..

}catch(Exception ex){

}

上面这种写法不建议,应该对具体异常分类处理。

4.尽量减小try代码块

来自为知笔记(Wiz)

时间: 2024-07-30 13:09:57

Java异常处理之最佳实践的相关文章

【译】异常处理的最佳实践

译注:这是一篇2003年的文章,因为时间久远,可能有些观点已经过时,但里面讨论的大部分方法如今仍能适用. Best Practices for Exception Handling 异常处理的重要一点就在于知道何时处理异常以及如何使用异常.在这篇文章里,我会提到一些异常处理的最佳实践,我也会总结checked exception的用法. 我们程序员都想写出高质量的代码来解决问题.不幸的是,异常会给我们的代码带来副作用.没有人喜欢副作用,所以我们很快找到了方法来改善它们.我看见过许多聪明的程序员这

JAVA 单实例最佳实践

1.public class Singleton { private static class SingletonHolder { public static Singleton resource = new Singleton(); public static Singleton getResource() { return SingletonHolder.resource ; private Singleton(){ 2.public class Singleton { public sta

避免Java中NullPointerException的Java技巧和最佳实践

Java中的NullPointerException是我们最经常遇到的异常了,那我们到底应该如何在编写代码是防患于未然呢.下面我们就从几个方面来入手,解决这个棘手的?问题吧.? 值得庆幸的是,通过应用一些防御性编码技术并遵循应用程序多个部分之间的约定,您可以在一定程度上避免Java中的NullPointerException. 顺便说一下,在本文中,我们将学习一些Java的编码技术和最佳实践,这些技巧和最佳实践可用于避免的Java中的空指针异常.遵循这些Java的技巧还可以最大程度地减少很多Ja

java 导出 excel 最佳实践,java 大文件 excel 避免OOM(内存溢出) exce

产品需求 产品经理需要导出一个页面的所有的信息到 EXCEL 文件. 需求分析 对于 excel 导出,是一个很常见的需求. 最常见的解决方案就是使用 poi 直接同步导出一个 excel 文件. 客户体验 & 服务性能 客户体验 如果导出的文件比较大,比如几十万条数据,同步导出页面就会卡主,用户无法进行其他操作. 服务性能 导出的时候,任务比较耗时就会阻塞主线程. 如果导出的服务是暴露给外部(前后端分离),这种大量的数据传输十分消耗性能. 解决方案 使用异常处理导出请求,后台 MQ 通知自己进

java 读取文件最佳实践

1.  前言 Java应用中很常见的一个问题,如何读取jar/war包内和所在路径的配置文件,不同的人根据不同的实践总结出了不同的方案,但其他人应用却会因为环境等的差异发现各种问题,本文则从原理上解释最佳实践. 2.  参考方案 2.1.log4j log4j读取配置的代码是: PropertyConfigurator.configure(“log4j.properties”); 实际执行的文件读取是: FileInputStream istream = new FileInputStream(

Java Bean Validation 最佳实践

参数校验是我们程序开发中必不可少的过程.用户在前端页面上填写表单时,前端js程序会校验参数的合法性,当数据到了后端,为了防止恶意操作,保持程序的健壮性,后端同样需要对数据进行校验.后端参数校验最简单的做法是直接在业务方法里面进行判断,当判断成功之后再继续往下执行.但这样带给我们的是代码的耦合,冗余.当我们多个地方需要校验时,我们就需要在每一个地方调用校验程序,导致代码很冗余,且不美观. 那么如何优雅的对参数进行校验呢?JSR303就是为了解决这个问题出现的,本篇文章主要是介绍 JSR303,Hi

.NET中异常处理的最佳实践(转)

原文地址:http://www.cnblogs.com/xiaozhi_5638/p/4259115.html 目录 介绍 做最坏的打算 提前检查 不要信任外部数据 可信任的设备:摄像头.鼠标以及键盘 “写操作”同样可能失效 安全编程 不要抛出“new Exception()” 不要将重要的异常信息存储在Message属性中 每个线程要包含一个try/catch块 捕获异常后要记录下来 不要只记录Exception.Message的值,还需要记录Exception.ToString() 要捕获具

.NET中异常处理的最佳实践(译)

本文翻译自CodeProject上的一篇文章,原文地址. 目录 介绍 做最坏的打算 提前检查 不要信任外部数据 可信任的设备:摄像头.鼠标以及键盘 "写操作"同样可能失效 安全编程 不要抛出"new Exception()" 不要将重要的异常信息存储在Message属性中 每个线程要包含一个try/catch块 捕获异常后要记录下来 不要只记录Exception.Message的值,还需要记录Exception.ToString() 要捕获具体的异常 不要中止异常上

Java多线程并发最佳实践

使用本地变量 尽量使用本地变量,而不是创建一个类或实例的变量. 使用不可变类 String.Integer等.不可变类可以降低代码中需要的同步数量. 最小化锁的作用域范围:S=1/(1-a+a/n) a:并行计算部分所占比例 n:并行处理结点个数 S:加速比 当1-a等于0时,没有串行只有并行,最大加速比 S=n 当a=0时,只有串行没有并行,最小加速比 S = 1 当n→∞时,极限加速比 s→ 1/(1-a) 例如,若串行代码占整个代码的25%,则并行处理的总体性能不可能超过4. 该公式称为: