tl; dr
此页面上的其他大多数答案都遵循“断言通常不在生产代码中使用”的格言。在生产力应用程序(如文字处理器或电子表格)中为true,而在Java如此常用的自定义业务应用程序中,assertion-生产中的测试非常有用,而且很普遍。
就像编程世界中的许多格言一样,在一个上下文中最初是正确的,然后在其他上下文中则错误地使用了它。
生产力应用
这种“断言在生产代码中通常不使用”的格言虽然很普遍,但却是不正确的。
正式的断言测试起源于诸如Word Word之类的文字处理器或Microsoft Excel之类的电子表格之类的应用。这些应用可能会在用户每次按键时调用一系列断言测试断言。这样的极端重复严重影响了性能。因此,只有在有限发行中的此类产品的beta版本才启用断言。因此,格言。
商业应用
相反,在用于数据输入,数据库或其他数据处理的面向业务的应用程序中,在生产中使用断言测试非常有用。对性能的微小影响使其非常实用,而且很常见。
测试业务规则
在生产中的运行时验证业务规则是完全合理的,应该鼓励这样做。例如:
- 如果发票必须始终有一个或多个订单项,则编写一个断言测试,以使发票订单项的计数大于零。
- 如果产品名称必须至少包含3个字符,请编写一个断言来测试字符串的长度。
- 在计算现金分类帐的余额时,您知道结果永远不会为负,因此请对负数进行检查以表明数据或代码有缺陷。
此类测试对生产性能没有重大影响。
运行时条件
如果您的应用程序期望某些条件在生产环境中运行时始终为真,则将这些期望值作为断言测试写入到您的代码中。
如果你希望这些条件可以合理偶尔失败,然后做不写断言测试。也许抛出某些例外。然后尝试尽可能恢复。
健全性检查
生产中在运行时进行健全性检查也是完全合理的,应该鼓励这样做。测试一些无法想象不真实的任意条件,使我的培根在数不清的情况下得救了。
例如,测试将某个镍中的镍(0.05)四舍五入会导致某个库中的镍(0.05),这使我成为第一批发现Apple在其Rosetta库中提供的浮点技术缺陷的人之一。从PowerPC到Intel的过渡。这样的缺陷似乎无法实现。但是令人惊讶的是,该漏洞没有引起原始厂商,Transitive和Apple以及早期访问开发人员在Apple Beta上进行测试的注意。
(顺便说一句,我应该提到...切勿使用浮点数赚钱,请使用BigDecimal
。)
框架选择
assert
您可能要考虑使用另一个断言框架,而不是使用内置工具。您有多种选择,包括:
或自己动手。制作一个小类以在您的项目中使用。这样的事情。
package work.basil.example;
public class Assertions {
static public void assertTrue ( Boolean booleanExpression , CharSequence message ) throws java.lang.AssertionError {
if ( booleanExpression ) {
} else {
throw new java.lang.AssertionError( message.toString() );
}
}
}
用法示例:
Assertions.assertTrue(
localTime.isBefore( LocalTime.NOON ) ,
"The time-of-day is too late, after noon: " + localTime + ". Message # 816a2a26-2b95-45fa-9b0a-5d10884d819d."
) ;
你的问题
他们来得相对较晚(Java 1.4),到那时,许多人已经建立了Java编程风格/习惯
是的,这是真的。Sun / JCP开发的用于断言测试的API使很多人感到失望。与现有库相比,其设计乏善可陈。许多人忽略了新的API,而使用了已知的工具(第三方工具或自带的微型库)。
默认情况下会在运行时将其关闭,为什么?
最早的几年里,Java因性能低下而受到了不满。具有讽刺意味的是,Java迅速发展成为性能最佳的平台之一。但是糟糕的说唱却像臭味一样散落。因此,Sun非常警惕任何可能以可衡量的方式影响性能的事情。因此,从这个角度来看,禁用断言测试默认值是有意义的。
默认情况下禁用的另一个原因可能与以下事实有关:在添加新的断言功能时,Sun劫持了这个词assert
。这不是以前保留的关键字,需要对Java语言进行的少数更改之一。assert
许多库和许多开发人员在自己的代码中都使用了方法名称。有关此历史过渡的一些讨论,请阅读此旧文档“使用断言编程”。