何时使用断言以及何时使用异常

com*_*tta 114 java exception assertion

大多数时候我会使用异常来检查代码中的条件,我想知道什么时候使用断言是合适的时间?

例如,

Group group=null;
try{
    group = service().getGroup("abc");
}catch(Exception e){
    //I dont log error because I know whenever error occur mean group not found
}

if(group !=null)
{
    //do something
}
Run Code Online (Sandbox Code Playgroud)

你能指出断言如何适应这里吗?我应该使用断言吗?

看起来我从不在生产代码中使用断言,只在单元测试中看到断言.我知道在大多数情况下,我可以使用异常来执行上面的检查,但我想知道"专业"的适当方式.

Gre*_*osz 164

出于我的想法(列表可能不完整,并且太长而无法容纳评论),我会说:

  • 检查传递给公共或受保护方法和构造函数的参数时使用异常
  • 在与用户交互时或在您希望客户端代码从异常情况中恢复时使用异常
  • 使用异常来解决可能发生的问题
  • 在检查前置条件,后置条件和私有/内部代码的不变量时使用断言
  • 使用断言为您自己或您的开发团队提供反馈
  • 在检查不太可能发生的事情时使用断言否则意味着你的应用程序中存在严重的问题
  • 使用断言来陈述你(据说)知道的事情

换句话说,异常解决了应用程序的健壮性,而断言解决了它的正确性.

断言的编写成本很低,几乎可以在任何地方使用它们而且我使用这个经验法则:断言语句看起来越愚蠢,它越有价值,它嵌入的信息就越多.在调试不正常的程序时,您一定会根据您的经验检查更明显的故障可能性.然后你将检查那些不可能发生的问题:这正是断言有助于节省时间的时候.

  • 我喜欢你的措辞:_Exceptions解决应用程序的健壮性,而断言解决了它的正确性. (50认同)

Mar*_*ius 79

应该使用断言来检查不应该发生的事情,而应该使用异常来检查可能发生的事情.

例如,函数可能除以0,因此应该使用异常,但可以使用断言来检查硬盘驱动器是否突然消失.

断言会阻止程序运行,但异常会让程序继续运行.

请注意,这if(group != null)不是一个断言,这只是一个条件.

  • 关于硬盘的评论是错误的.断言用于检查代码逻辑中的错误.永远不要用它们来检查你无法控制的东西.请记住,**如果断言失败,则意味着您的代码错误**. (65认同)
  • "断言可以用来检查硬盘突然消失" - 我说这是不正确的:你为什么要在开发期间处理这个问题,而不是在生产中(当断言通常被禁用时)? (3认同)
  • 被否决是因为硬盘驱动器示例与您自己的理念相矛盾。硬盘“消失”(从代码的角度来看)实际上可能会在现实中发生——无论多么不可能。就像@IanGoldby 说的那样,断言应该完全取决于由您的代码控制的事物。 (2认同)

chb*_*urd 25

请记住,可以在运行时使用参数禁用断言,默认情况下禁用断言,因此除了调试目的外,不要依赖它们.

另外,您应该阅读有关assertOracle文章,以查看更多使用 - 或不使用 - 断言的情况.


Ste*_*n C 15

作为基本规则:

  • 使用断言进行内部一致性检查,如果有人将其关闭则根本不重要.(注意,该java命令默认关闭所有断言.)
  • 使用常规测试进行任何不应关闭的检查.这包括防御性检查,防止由错误导致的潜在损害,以及任何验证数据/请求/用户或外部服务提供的任何内容.

您的问题中的以下代码是糟糕的风格潜在的错误

try {
    group = service().getGroup("abc");
} catch (Exception e) {
    //i dont log error because i know whenever error occur mean group not found
}
Run Code Online (Sandbox Code Playgroud)

问题是你不知道异常意味着找不到该组.service()调用也可能抛出异常,或者返回异常null然后导致异常NullPointerException.

当您捕获"预期"异常时,您应该捕获您期望的异常.通过捕获java.lang.Exception(尤其是不记录它),您将更难以诊断/调试问题,并可能使应用程序造成更多损害.