何时使用断言以及何时使用exception

大多数情况下,我将使用一个exception检查代码中的条件,我想知道什么时候使用断言是合适的。

例如,

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 } 

你能指出一个断言是如何适应的吗? 我应该使用断言吗?

看起来我从来没有在生产代码中使用断言,只能在unit testing中看到断言。 我知道在大多数情况下,我可以只使用exception来进行上面的检查,但我想知道适当的方式来“专业”。

应该使用断言来检查不应该发生的事情,而应该使用exception来检查可能发生的事情。

例如,一个函数可能会被0除,所以应该使用一个exception,但是一个断言可以用来检查硬盘突然消失。

一个断言会阻止程序运行,但是一个exception会让程序继续运行。

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

出于我的想法(名单可能不完整,而且太长以至于无法置评),我会说:

  • 检查传递给公共或受保护方法和构造函数的参数时使用exception
  • 与用户进行交互时或者希望客户端代码从特殊情况中恢复时使用exception
  • 使用例外来解决可能发生的问题
  • 在检查私有/内部代码的先决条件,后置条件和不variables时使用断言
  • 使用断言向自己或您的开发人员团队提供反馈
  • 在检查不太可能发生的事情时使用断言,否则就意味着应用程序中存在严重的错误
  • 使用断言陈述你(据说)知道是真实的东西

换句话说,exception解决了你的应用程序的健壮性,而断言解决了它的正确性。

断言的devise很便宜,你可以在任何地方使用它们,我使用这个经验法则:断言声明越是愚蠢,它就越有价值,它embedded的信息就越多。 在debugging不正确的程序时,根据您的经验,您一定会检查更明显的故障可能性。 然后,您将检查是不可能发生的问题:这正是断言帮助很多,节省时间。

请记住断言可以在运行时使用参数禁用,默认情况下是禁用的 ,所以不要指望它们,除了debugging目的。

另外,您应该阅读Oracle关于断言的文章,以查看更多的情况下使用 – 或不使用 – 断言。

作为基本规则:

  • 使用断言进行内部一致性检查,如果有人将其closures,则根本无关紧要。 (请注意,默认情况下, java命令会closures所有断言。)
  • 使用常规testing进行任何不应该closures的检查。 这包括防止由错误引起的潜在损害的防御性检查以及任何validation数据/请求/由用户或外部服务提供的任何内容。

你的问题下面的代码是不好的风格潜在的错误

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

问题是,你不知道一个例外意味着没有find该组。 service()调用也可能抛出exception,或者返回null ,然后导致NullPointerException

当你捕捉到一个“预期的”exception时,你应该捕获你所期望的exception。 通过捕获java.lang.Exception (特别是通过不logging它),您正在使诊断/debugging问题变得更加困难,并且可能会让应用程序造成更多的损害。

根据这个文档http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#design-faq-general,“assert语句适用于非公共先决条件,后置条件和类不variables公共前提条件检查仍然应该通过检查内部方法来执行,这些方法会导致特定的exception情况,如IllegalArgumentException和IllegalStateException。;

如果您想了解更多关于先决条件,后置条件和类不变的信息,请查看以下文档: http : //docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#usage-conditions 。 它也包含断言用法的例子。

那么回到微软,我们的build议就是在你公开提供的所有API中抛出exception,并在你对内部代码进行各种假设时使用Asserts。 这是一个松散的定义,但我想这是由每个开发人员来画线。

关于exception的使用,顾名思义,它们的用法应该是例外的,所以对于上面的代码,如果没有服务存在, getGroup调用应该返回null 。 只有在networking连接断开或类似的情况下才会发生exception。

我想结论是,对于每个应用程序来说,开发团队都要定义assert vs exceptions的边界。

对null进行testing只会导致空值导致问题,而try / catch则会捕获任何错误。

一般来说,try / catch是比较安全的,但稍微慢一点,你必须小心,以避免可能发生的各种错误。 所以我会说使用try / catch – 有一天getGroup代码可能会改变,你可能需要更大的networking。

你可以使用这个简单的差异,而他们的使用。 exception将用于检查期望的和意外的错误,称为检查错误或未检查错误,而断言主要用于运行时的debugging目的,以查看假设是否被validation。

我承认你的问题让我有些困惑。 当断言条件不满足时,抛出exception。 令人困惑的是,这被称为AssertionError 。 请注意,它没有被选中,就像(例如)在非常相似的情况下抛出IllegalArgumentException一样。

所以在Java中使用断言

  1. 是写一个条件/投掷块更简洁的手段
  2. 允许您通过JVM参数打开/closures这些检查。 通常我会一直离开这些检查,除非它们影响运行时性能或者有类似的惩罚。

请参阅以下链接中Sun文档的6.1.2节(断言与其他错误代码)。

http://www.oracle.com/technetwork/articles/javase/javapch06.pdf

本文给出了我在使用断言时看到的最好的build议。 从文档引用:

“一个好的经验法则就是,你应该为你想要忘记的例外情况使用一个断言,一个断言是处理和忘记一个你不需要的条件或状态的最快方法处理。”

不幸的是断言可以被禁用。 在生产过程中,你需要寻找一些无法预料的事情时所能得到的帮助,因此断言自己不合格。