suchen

Heim  >  Fragen und Antworten  >  Hauptteil

java - Warum wird nicht empfohlen, RuntimeException direkt im Code auszulösen?

Die Verwendung allgemeiner Ausnahmen wie Error, RuntimeException, Throwable und Exception verhindert, dass aufrufende Methoden echte, vom System generierte Ausnahmen anders behandeln als von der Anwendung generierte Fehler.

Beispiel für nicht konformen Code


public void foo(String bar) throws Throwable {  // Noncompliant
  throw new RuntimeException("My Message");     // Noncompliant
}

Konforme Lösung


public void foo(String bar) {
  throw new MyOwnRuntimeException("My Message");
}
曾经蜡笔没有小新曾经蜡笔没有小新2703 Tage vor1488

Antworte allen(5)Ich werde antworten

  • 滿天的星座

    滿天的星座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是动态的, 那将无法准确的处理.
    当然我们也可以定义一个通用的异常类型, 通过业务码去判断会更加准确, 同时也会减少异常类型的定义, 减少代码的冗余. 下面有一段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
    }

    Antwort
    0
  • 女神的闺蜜爱上我

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

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

    Antwort
    0
  • 扔个三星炸死你

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

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

    Antwort
    0
  • 怪我咯

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

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

    Antwort
    0
  • typecho

    typecho2017-06-30 09:58:07

    运行时异常不需要捕获

    Antwort
    0
  • StornierenAntwort