在 Java 中使用 AssertionError 和断言 [英] Using AssertionError and assertions in java

查看:38
本文介绍了在 Java 中使用 AssertionError 和断言的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以标准方式在 Java 中使用断言,并在我的 IDE 中打开它们.所以它们不是生产版本的一部分.最近我看到了带有 throw new AssertionError() 的代码示例,我开始思考应该使用 AssertionError 而不是断言的情况.

I use assertions in Java in a standard way, having them turned on in my IDE. So they are not part of production release. Lately I have been seeing code examples with throw new AssertionError() and I started thinking about the situation where AssertionError should be used instead of assertion.

我的猜测是,主要区别在于断言的可选性,因此它们不会降低生产性能,因此它们可以经常出现在代码中,但修复用户报告的几乎不可重现的错误更难.

My guess is that main difference is the optionality of asserts so they don't slow down the production performance and so they can occur quite often in the code, but fixing hardly reproducible bugs reported from users is harder.

对于AssertionError,正好相反.

我还发现 AssertionError 在代码中不应该执行的地方更实用,而不是使用 assert false//We should not be here.特别是如果需要返回值.例如:

I also find AssertionError more practical in places in code where the execution should not get, instead of using assert false //We should not be here. Especially if the return value is required. For example:

int getFoo(AnEnum a){
    if (a == AnEnum.ONE)
       return bar();
    else if (a == AnEnum.TWO)
       return SOME_VALUE;
    //else
    assert false; //throw new AssertionError();
    return -1; //not necessary when usin AssertionError
}

  • 我的推理是否正确?
  • 其他区别/用例/最佳实践/限制是什么两种方法?
  • 关于在 AssertionError 中提供描述 - 应该提供它还是仅仅是一个 Error 的事实(和断言类型)足以或多或少地确定堆栈跟踪会在发现错误时提供吗?
    • Is my reasoning correct?
    • What are the other differences/use cases/best practices/limitations of either approach?
    • In regards to providing a description in the AssertionError - Should it be provided or is the mere fact that it is an Error (and of assertion type) enough to be more or less sure that stack trace will be provided in case of found bugs?
    • 推荐答案

      我建议不要直接抛出 AssertionError .如果您选择依赖 AssertionErrors 来检查不变量、前置/后置条件、状态条件等,你仍然最好使用常规断言,并在生产中打开-ea"标志作为好吧.
      原因是断言机制(除了在编译器级别进行优化)让您有机会一次打开或关闭所有断言.即使你现在想不出这样做的理由,如果你将来遇到一个理由,只要考虑一下你必须检查所有的 throw new AssertionError(...) 键入代码并用一个讨厌的 if 子句将其包围.你得到了图片.
      正如您不希望将幻数硬编码到代码中的许多地方,并且可能会使用常量代替,您不应该用许多重复来感染您的代码(即 throw new AssertionError(...) 部分).

      I would advise against throwing AssertionErrors directly. If you choose to rely on AssertionErrors for checking invariants, pre/post conditions, state conditions, etc. you're still better off using regular assertions with the "-ea" flag turned on in production as well.
      The reason is that the assertions mechanism (other than being optimized at the compiler level) gives you a chance to turn on or off all assertions at once. Even if you can't think of a reason to do that now, if you come across a reason in the future, just consider that you'll have to go over all your throw new AssertionError(...) type code and surround it with a nasty if clause. You get the picture.
      Just as you wouldn't want a magic number hard coded into many places in your code, and would probably use a constant instead, you shouldn't infect your code with many duplications (i.e. the throw new AssertionError(...) part).

      关于断言的另一种说法.我相信您在依赖生产代码中的断言错误之前应该三思而后行.原因是 AssertionError 是非常通用的.它有一个信息和一个原因,但仅此而已.
      考虑改为使用特定的 RuntimeException 子类,这些子类将通过属于与问题更相关的特定类以及携带与问题相关的实际数据来传达更多信息.
      作为一个简单的例子,考虑您在问题中提到的一个案例,其中有一些您不希望到达的代码部分.断言或 AssertionError 将传达这样一个事实,即您到达了一些意外代码,但仅此而已.使用特定的 RuntimeException 还可以及时传递方法的局部变量和参数的状态.您可能会争辩说,通过设置断言或 AssertionError 的消息来包含此信息,这是可行的,但这在使用自动错误记录/处理机制时不起作用.此类机制可以使用访问者模式在您用来检查意外行为的 RuntimeException 的不同子类上处理意外行为(通过句柄我也指快速失败,不一定是恢复).

      Another word about assertions though. I believe that you should think twice before relying on assertion errors in production code. The reason is that an AssertionError is very generic. It has a message and a cause, but that's pretty much it.
      Consider instead using specific RuntimeException subclasses that will convey more information both by being of a specific class more related to the problem, as well as by carrying actual data related to the problem.
      As a simple example, consider a case you mentioned in your question where there's some part of the code that you don't expect to reach. An assertion or an AssertionError would convey the fact that you reached some unexpected code, but not much more. Using a specific RuntimeException could also deliver the state of the local variables and parameters of the method at that point in time. You could argue that this is doable with setting the message of the assertion or AssertionError to contain this information, but this does not work when using automatic error logging/handling mechanisms. Such mechanisms can handle unexpected behaviors using the visitor pattern on the different sub classes of RuntimeException you're using to check unexpected behavior (by handle I also mean fail-fast, not necessarily recovery).

      这篇关于在 Java 中使用 AssertionError 和断言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆