搜索

首页  >  问答  >  正文

java - 为什么在代码中不建议直接抛RuntimeException呢?

使用 Error、RuntimeException、Throwable 和 Exception 等通用异常可防止调用方法以不同于应用程序生成的错误的方式处理真正的系统生成的异常。

不合规代码示例

雷雷

合规解决方案

雷雷
曾经蜡笔没有小新曾经蜡笔没有小新2702 天前1485

全部回复(5)我来回复

  • 滿天的星座

    滿天的星座2017-06-30 09:58:07

    这个很容易理解啊.
    打个简单的比方. 现在做一个登录有用户不存在/密码错误... 这些错误类型, 如果你直接使用RuntimeException 代码要写成这样.

    throw new RuntimeException("user not found"); // 用户不存在
    throw new RuntimeException("password not match"); // 密码错误

    捕捉异常

    try {
        // ...逻辑
    } catch(RuntimeException e) {
        if("user not found".equals(e.getMessage())) {
            // ...逻辑
        } else if("password not match".equals(e.getMessage())) {
            // ...逻辑
        }
    }

    反之自定义异常实现如下:

    throw new UserNotFoundException("user not found"); // 用户不存在
    throw new PasswordNotMatchException("password not match"); // 密码错误

    捕捉异常

    try {
        // ...逻辑
    } catch(UserNotFoundException e) {
        // ...逻辑
    } catch(PasswordNotMatchException e) {
        // ...逻辑
    }

    通过message判断处理异常逻辑有很多弊端, 比如message是动态的, 那将无法准确的处理.message判断处理异常逻辑有很多弊端, 比如message是动态的, 那将无法准确的处理.
    当然我们也可以定义一个通用的异常类型, 通过业务码去判断会更加准确, 同时也会减少异常类型的定义, 减少代码的冗余. 下面有一段kotlin当然我们也可以定义一个通用的异常类型, 通过业务码去判断会更加准确, 同时也会减少异常类型的定义, 减少代码的冗余. 下面有一段kotlin代码, 目前我是使用的这种处理方式.

    interface BizCode {
    
        val code: Int
        val msg: String
    }
    
    enum class BizCodes(override val code: Int, override val msg: String): BizCode {
    
        // ====================================================== //
        // 公共错误码 0 - 999                                      //
        // ====================================================== //
        /**
         * 未知错误.
         */
        C_0(0, "未知错误"),
        /**
         * HTTP Request 参数错误.
         */
        C_999(999, "HTTP Request 参数错误"),
    
        // ====================================================== //
        // client 错误码 1000 - 1999                               //
        // ====================================================== //
        /**
         * 未发现指定 client_id 客户端记录.
         */
        C_1000(1000, "未发现指定 client_id 客户端记录"),
        C_1001(1001, "client_secret 不匹配"),
    
        // ====================================================== //
        // user 错误码 2000 - 2999                                //
        // ====================================================== //
    
        /**
         * 未发现指定 email 的用户.
         */
        C_2000(2000, "未发现指定 email 的用户"),
        C_2011(2011, "password 不匹配"),
    
        //
        ;
    
        override fun toString(): String {
            return "[$code] $msg"
        }
    }
    
    class BizCodeException : RuntimeException {
    
        val bizCode: BizCode
    
        constructor(bizCode: BizCode) : super(bizCode.toString()) {
            this.bizCode = bizCode
        }
    
        constructor(bizCode: BizCode, e: Exception) : super(bizCode.toString(), e) {
            this.bizCode = bizCode
        }
    
        override fun fillInStackTrace() = this
    }

    回复
    0
  • 女神的闺蜜爱上我

    女神的闺蜜爱上我2017-06-30 09:58:07

    说明的挺清楚了啊,方便捕获处理

    回复
    0
  • 扔个三星炸死你

    扔个三星炸死你2017-06-30 09:58:07

    Exception名字要有意义,RuntimeException名字没有意义

    回复
    0
  • 怪我咯

    怪我咯2017-06-30 09:58:07

    Exception直接抛的话,Nginx 会把你定义message 覆盖掉,导致看不到具体信息。
    建议的做法是,自己定义一个exception,去继承 RuntimeException,这个就知道你的exception 是什么,也方便查找问题。

    回复
    0
  • typecho

    typecho2017-06-30 09:58:07

    运行时异常不需要捕获

    回复
    0
  • 取消回复