• JAVA异常使用_每个人都曾用过、但未必都用得好


    一、抛出异常 vs. 返回错误代码

    有人说“Well, an exception is a goto.”,但也有人言“makes the code simpler by visibly separating the general case of expected processing from the special cases of errors.”

     

    简单地分析一下两者优劣。异常的优点:让代码更简洁,不再到处if-return;无论CheckedEx还是UnCheckEx都会强迫调用方或系统处理;Exception Chain和继承体系,可以解耦检测错误和错误处理,方便包装异常和控制错误链;异常调试方便,可以跟踪到引发异常的源指令。异常的缺点,除了效率慢之外,最重要的一点是很难知道应该try-catch具体神马。例:

    badly exception-based exception

    not badly exception-based exception

    很难发现因为先初始化Visible=true、在new Icon时抛异常导致错误逻辑的情景。但对于ErrorCode而言,由于大量的if-return、更容易辨识逻辑的正确性。

    ErrorCode的优点在于清楚每一个具体的错误类型Code,但你一定不清楚可能捕获多少具体Exception;返回一种结果状态,如0〜成功、-1〜失败;将Error的传播层限制在父层,对于Exception Chain而言,“The thrower of an exception is specifically relinquishing the right to have any expectations about how the exception will be handled.”;易于CodeReview以及保证编写逻辑正确性,被用于编写操作系统、底层驱动等等。但有许多缺点,没有像Exception的链式处理等诸多优点,而且经常忘记检测返回是否成功、需要频繁变更ErrorCode等数据类型。

    对于Exception和ErrorCode而言,需要找到两者的平衡点,有以下一些原则:

    1、对于绝大部分代码而言,Exception更加安全,到少会有异常体系去处理,再不济也就程序异常 终止;但针对需要well-reviewed的关键代码,适宜采用ErrorCode;

    2、如果涉及到与业务逻辑相关的代码,最好采用ErrorCode;业务逻辑无关的代码,如传入参数校验,采用Exception;

    3、除了trying之外没有处理逻辑和更多优势的情况,最好采用Exception;

    4、远程接口实现中,仅采用ErrorCode。因为远程调用框架对Exception的支持度等具有较大差异。

    二、怎样抛出异常&ErrorCode

    仅当涉及到业务逻辑错误的情况下抛出异常,注意几点:

    1、一个系统中至多有3〜5个具体自定义异常,如ibatis就仅5个左右;

    2、如果Caller负责在调用之前检测条件,则应该抛出UnCheckedEx,否则抛出CheckedEx;

    3、远程调用一定要try-catch;

    4、ErrorCode应该采用Code+String形式,如:

    5、return ErrorCode应当采用“{object, error}”的形式,如:


    e.g:一个异常体系设计示例

    三、参数校验

    参数校验,是一类比较容易触发返回ErrorCode或抛Exception的行为。有类规则:

    1、Api入参校验采用Exception方式;

    2、允许出错的参数校验、采用ErrorCode方式。

    参数校验有几类常用包,如:

    com.google.common.base.Preconditions

    org.springframework.validation.ValidationUtils

    org.apache.commons.lang.Validate

    不太推荐使用Spring的ValidationUtils,太过依赖Spring框架、向后扩展性不强。Guava库的Preconditions vs. Apache的Validate:

    1、Preconditions校验可抛出不同异常,如checkArgument throws IllegalArgumentException、checkNotNull throws NullPointerException等,Validate则仅抛出一种IllegalArgumentException;

    2、Message参数,Preconditions适为灵活,Validate不支持StringFormat,如:

    Validate.isTrue(i > 0, "Should be positive but was: " + i);

    Validate.isTrue(i > 0, "Should be positive but was: ", i);

    checkArgument(i > MIN, "Expected more than %s, got %s", MIN, i);

    3、集合判断,Apache有几个额外的函数:

    • Validate.notEmpty(Collection collection)

    • Validate.notEmpty(Map map)

    • Validate.notEmpty(Object[] array)

    • Validate.noNullElements(Collection collection)

    • Validate.noNullElements(Object[] array)

    而Precondictions使用则比较麻烦:checkArgument(isNotEmpty(list));

    4、Precondictions可以一条语句搞定判断后赋值,this.field = checkNotNull(parameter);

    5、比较陈旧的系统,推荐使用Validate;


    http://c2.com/cgi/wiki?AvoidExceptionsWheneverPossible

    http://piotrjagielski.com/blog/google-guava-vs-apache-commons-for-argument-validation/



  • 相关阅读:
    Thinphp+nginx配置伪静态
    Potyczki Algorythmiczne 2013
    接下来一段时间会对大家进行网络通信的魔鬼训练理解socket
    项目中怎样做技术选型
    面试官问我:你做事仔细吗?
    【编程一生】2021年总结数据可视化技巧
    一个反直觉的sql
    CURD系统怎么做出技术含量惊艳面试官
    深入理解函数式编程
    历史文章分类汇总
  • 原文地址:https://www.cnblogs.com/icanth/p/3546562.html
Copyright © 2020-2023  润新知