断言一个好的做法与否?

2022-08-31 17:30:27

对函数参数使用 Assert 来强制其有效性是否是一种很好的做法。我正在浏览Spring Framework的源代码,我注意到它们使用了很多。下面是一个示例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;
}

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

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

答案 1

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

例如,Java 绑定在运行时检查所有数组访问。这会让事情变得慢一点吗?是的。它有益吗?绝对!一旦发生越界冲突,就会引发异常,并向程序员发出任何可能的 bug 的警报!在不对阵列访问进行边界检查的其他系统中,行为更加不可预测!(通常会带来灾难性的后果!

断言,无论你使用库还是语言支持,在精神上都是相似的。有性能成本,但这绝对是值得的。事实上,断言更有价值,因为它是显式的,并且它传达了更高层次的概念。

如果使用得当,性能成本可以最小化,并且对于客户(他们迟早会发现违反合同的行为)和开发人员(因为合同是自我执行自我记录的)的价值最大化。

另一种看待它的方式是将断言视为“主动评论”。没有人认为评论是有用的,但它们是被动的;在计算上,他们什么都不做。通过将一些概念表述为断言而不是注释,它们变得活跃起来。它们实际上必须在运行时保持;违规行为将被捕获。


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


答案 2

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

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

在我看来(就其价值而言),这是一种与任何验证参数的方法一样好的方法。如果您像问题标题所暗示的那样使用了内置断言,我会以必要的检查不应该被删除为由反对它。但这种方式只是以下简写:

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

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

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


推荐