认定一个好的做法或不?

使用Assert作为函数参数来强制执行它是一个好习惯。 我正在浏览Spring框架的源代码,我注意到它们使用Assert.notNull很多。 这是一个例子

  public static ParsedSql parseSqlStatement(String sql) { Assert.notNull(sql, "SQL must not be null");} 

这是另一个:

 public NamedParameterJdbcTemplate(DataSource dataSource) { Assert.notNull(dataSource, "The [dataSource] argument cannot be null."); this .classicJdbcTemplate = new JdbcTemplate(dataSource); } public NamedParameterJdbcTemplate(JdbcOperations classicJdbcTemplate) { Assert.notNull(classicJdbcTemplate, "JdbcTemplate must not be null"); this .classicJdbcTemplate = classicJdbcTemplate; } 

仅供参考, Assert.notNull (不是assert语句)在util类中定义如下:

 public abstract class Assert { public static void notNull(Object object, String message) { if (object == null) { throw new IllegalArgumentException (message); } } } 

原则上, 断言与许多其他运行时检查没有什么不同。

例如,Java在运行时绑定检查所有数组访问。 这会让事情变慢吗? 是。 这是有益的吗? 绝对! 一旦出现违规违规,就会抛出exception,并提醒程序员任何可能的错误! 数组访问没有被绑定的其他系统中的行为是非常不可预知的! (往往带来灾难性的后果!)。

断言,无论你使用图书馆还是语言支持,在精神上是相似的。 性能成本,但它是绝对值得的。 事实上,断言更为重要,因为它是明确的,它传递更高层次的概念。

如果使用得当,可以最大限度地降低性能成本,并且最大限度地为客户(他们将尽早而不是晚些时候捕获合同违规)和开发人员(因为合同是自我执行自我logging )的价值。

另一种看待它的方法是将断言看作“积极的评论”。 没有人认为评论是有用的,但他们是被动的; 在计算上他们什么都不做。 通过将一些概念expression为断言而不是评论,它们变成活动的。 他们实际上必须在运行时间保持; 违规行为将被捕获。


另请参见: 使用断言进行编程的好处

这些断言是库提供的,与内置的assert关键字不一样。

这里有一个区别:默认情况下, assert s不运行(它们必须使用-ea参数启用),而Assert类提供的Assert不能被禁用。

在我看来(这是值得的),这与validation参数一样好。 如果你使用内置的断言作为问题的标题,我会反驳它,因为必须的检查不应该是可移动的。 但是这种方式只是简单的:

 public static ParsedSql parseSqlStatement(String sql) { if (sql == null) throw new IllegalArgumentException("SQL must not be null"); ... } 

这在公共方法上总是很好的做法。

断言的内置样式对于条件始终为真的情况或私有方法更有用。 介绍断言的语言指南有一些很好的指导方针,基本上我刚刚描述过。

是的,这是很好的做法。

在Spring情况下,这一点尤其重要,因为这些检查正在validation属性设置等,这些属性设置通常来自XML配线文件。 换句话说,他们正在validationwebapp的configuration。 如果你曾经做过任何严肃的基于Spring的开发,那么当你犯了一个愚蠢的configuration错误时,这些validation检查将会为你节省数小时的debugging时间。

但请注意,名为Assert的库类与用于定义Java断言的Java assert关键字之间存在巨大差异。 后一种forms的断言可以在应用程序启动时closures,不应该用于您始终想要发生的参数validation检查。 显然,Spring的devise者认为closureswebappconfiguration的完整性检查是一个非常糟糕的主意……我同意。

UPDATE

在Java 7(及更高版本)中, java.util.Objects类提供了一个requireNonNull便捷方法来testing参数是否为null并引发exception。 你这样使用它:

  SomeType t = ... SomeType tChecked = Objects.requireNonNull(t); 

要么

  SomeType tChecked = Objects.requireNonNull(t, "t should be non-null"); 

但是,请注意,此方法引发NullPointerException而不是IllegalArgumentException

基于Sun关于断言的指导 ,您不应该使用断言来进行公共方法中的参数检查。

参数检查通常是方法发布的规范(或契约)的一部分,无论断言是启用还是禁用,都必须遵守这些规范。

在非常大且devise不当的系统中,如果您希望提高6000线的可预测性,并且公司中没有人再理解这些方法,那么使用assert关键字来引发开发环境可能是有价值的炸毁,暴露的错误。 但是,如果你在生产中实施这些说法,你可能会缩短一个补丁,尽pipe可怕的构思,但修补了一个问题。 你想通过在开发环境中发现而不是在生产中修复那个不好的补丁。 所以你可以在开发时打开它,并在生产中closures它们。

开发时assert关键字的另一个有效用法是将有效性检查插入algorithm中,该algorithm必须在亚毫秒时间内执行,并且与不可预知的或未经testing的调用者完全隔离。 在这种情况下,您可能无法保留生产中的有效性检查,尽pipe它在开发中仍然非常有用。 另一方面,如果您正在validation的参数的来源是不可预知的,或者可能变得如此(例如,如果部分由用户input确定),则即使在生产中,也可能永远不能跳过检查,并且应该把业绩打到做生意的成本。 (在最后一种情况下,您可能不想使用断言)。但是, 只有在性能分析告诉您无法负担开销后,您才应该select断言来消除生产时间有效性检查。

是的,这是一个好主意。 你正在执行界面或类的承包。 如果违反合同,您希望尽快发现。 您等待的时间越长,结果越难以预测,诊断就越困难。

当你像这样明确地检查的时候,你也应该提供一个信息消息,当在日志文件中查看时,可以给出有用的上下文来帮助find根本原因,甚至只是意识到你对合同的错误假设。

我保持我的断言发布的二进制文件,但修改后的行为:中止不被调用,但堆栈跟踪收集。

更多细节在这里: http : //blog.aplikacja.info/2011/10/assert-to-abort-or-not-to-abort-thats-the-question/