断言好的做法与否?

ken*_*ken 49 java assert

将Assert用于函数参数以强制执行其有效性是一种好习惯.我正在浏览Spring Framework的源代码,我注意到它们使用Assert.notNull了很多.这是一个例子

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

这是另一个:

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;
      }
Run Code Online (Sandbox Code Playgroud)

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

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

pol*_*nts 58

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

例如,Java绑定 - 在运行时检查所有数组访问.这会让事情变慢吗?是.这有益吗?绝对!一旦发生越界违规,就会抛出异常并且程序员会收到任何可能的错误警报!未对数组访问进行绑定检查的其他系统中的行为更加难以置信!(通常带来灾难性的后果!).

无论您使用图书馆还是语言支持,断言在精神上都是相似的.有性能成本,但绝对值得.事实上,断言更有价值,因为它是明确的,并且它传达了更高层次的概念.

如果使用得当,可以最大限度地降低性能成本,并且最大限度地提高客户(将尽快捕获合同违规)和开发人员(因为合同是自我执行自我记录)的价值.

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


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

  • 我的印象是可以关闭断言.这不会破坏使用断言的整个目标吗? (6认同)
  • 不是100%肯定这一点,但我认为这取决于应用程序的类型.我依稀记得在Code Complete中读到这个.假设你有一个带有嵌入式java程序的医疗设备.它将在启用断言的情况下运行,因此它将崩溃而不是返回错误的读数,您只需重新启动并再次使用它.另一方面,假设它是一个游戏,可能发生的更糟糕的是屏幕上的像素是错误的颜色,你可以在生产中禁用断言.好吧,至少这是我的理解.这个答案非常有启发性. (2认同)
  • 我忘了补充说:那只是为了生产.通常,您将在测试期间启用断言,因此,至少在您可以完全控制启用断言的特定场景(测试,开发)中,您不会失去优势. (2认同)
  • 在我的大学,我们有一门课程使用断言(Design By Contract 风格)。对我们来说,断言是为了确保我们不会意外地践踏我们的数据,并导致段错误。一旦我们想从代码中获得一些真正的速度,并且在我们对小案例运行断言之后,我们就关闭了断言/合同。 (2认同)
  • @monksy - 使用`assert`实现的断言可以使用JVM命令行选项关闭.根据OP的示例实现的断言只有在类/方法被设计为允许时才能关闭. (2认同)

Mic*_*ers 28

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

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

在我看来(对于它的价值而言),这与验证参数的方法一样好.如果您使用内置断言作为问题标题暗示,我会反对它,因为必须检查不应该是可移除的.但这种方式只是简写:

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

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

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


Ste*_*n C 18

是的,这是好习惯.

在Spring的情况下,它特别重要,因为检查是验证通常来自XML连接文件的属性设置等.换句话说,他们正在验证webapp的配置.如果你做过任何严肃的基于Spring的开发,当你犯一个愚蠢的配置错误时,那些验证检查将为你节省数小时的调试时间.

但请注意,调用的库类Assertassert用于定义Java断言的Java 关键字之间存在巨大差异.后一种形式的断言可以在应用程序启动时关闭,不应该用于您总是希望发生的参数验证检查.显然,Spring设计师认为关闭webapp配置健全性检查是一个非常糟糕的主意......我同意.

UPDATE

在Java 7(及更高版本)中,java.util.Objects该类提供了一种requireNonNull方便的方法来测试参数是否存在null并引发异常.你这样使用它:

 SomeType t = ...
 SomeType tChecked = Objects.requireNonNull(t);
Run Code Online (Sandbox Code Playgroud)

要么

 SomeType tChecked = Objects.requireNonNull(t, "t should be non-null");
Run Code Online (Sandbox Code Playgroud)

但请注意,这种方法NullPointerException不是提高而是提高IllegalArgumentException.


kiw*_*ptn 6

基于Sun的指南上断言,您应该使用断言的争论在公共方法检查.

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

  • 这是'assert'关键字 - 而不是Commons Lang和Spring框架提供的Assert.*. (9认同)