何时使用断言以及何时使用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#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中使用断言
- 是写一个条件/投掷块更简洁的手段
- 允许您通过JVM参数打开/closures这些检查。 通常我会一直离开这些检查,除非它们影响运行时性能或者有类似的惩罚。
请参阅以下链接中Sun文档的6.1.2节(断言与其他错误代码)。
http://www.oracle.com/technetwork/articles/javase/javapch06.pdf
本文给出了我在使用断言时看到的最好的build议。 从文档引用:
“一个好的经验法则就是,你应该为你想要忘记的例外情况使用一个断言,一个断言是处理和忘记一个你不需要的条件或状态的最快方法处理。”
不幸的是断言可以被禁用。 在生产过程中,你需要寻找一些无法预料的事情时所能得到的帮助,因此断言自己不合格。