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

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

  •  java
  •  
  • spring
  •  
  • java-ee
  •  
  • springboot
  •  
  • mybatis

 4.3k 次浏览

问题对人有帮助,内容完整,我也想知道答案0问题没有实际价值,缺少关键内容,没有改进余地

Using such generic exceptions as Error, RuntimeException, Throwable, and Exception prevents calling methods from handling true, system-generated exceptions differently than application-generated errors.

Noncompliant Code Example


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

Compliant Solution


public void foo(String bar) {
  throw new MyOwnRuntimeException("My Message");
}
  • 关注 | 6
  • 收藏 | 1
  •  评论
  • 邀请回答
  • 编辑
  • 翻译
  •  

菩提旭光  2.7k

2017-06-28 提问

默认排序时间排序

5 个回答

答案对人有帮助,有参考价值3答案没帮助,是错误的答案,答非所问

这个很容易理解啊.
打个简单的比方. 现在做一个登录有用户不存在/密码错误... 这些错误类型, 如果你直接使用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
}
  •  评论 · 4
  • 赞赏
  • 编辑

kevinz  4.8k

2017-06-28 更新

答案对人有帮助,有参考价值1答案没帮助,是错误的答案,答非所问

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

  •  评论
  • 赞赏
  • 编辑

chanjarster  3.4k

2017-06-28 回答

答案对人有帮助,有参考价值0答案没帮助,是错误的答案,答非所问

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

  •  评论
  • 赞赏
  • 编辑

武可  1.4k

2017-06-28 回答

答案对人有帮助,有参考价值0答案没帮助,是错误的答案,答非所问

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

  •  评论
  • 赞赏
  • 编辑

nicce  104

2017-06-28 回答

答案对人有帮助,有参考价值-1答案没帮助,是错误的答案,答非所问

运行时异常不需要捕获

你可能感兴趣的:(Exception)