在java中使用AssertionError和断言

在java中使用AssertionError和断言

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

问题描述

我以标准的方式在Java中使用断言,让我们在IDE中打开它们。所以他们不是生产发行的一部分。最近我一直看到代码示例与抛出新的AssertionError(),我开始思考的情况,其中 AssertionError 应该是使用而不是断言。



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



对于 AssertionError ,恰恰相反适用。 / p>

我还发现在执行不应该得到的代码中更为实用的AssertionError 而不是使用 assert false //我们不应该在这里。特别是如果返回值是必需的。例如:

  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; //不需要当使用AssertionError
}




  • 是我的推理正确?

  • 任何一种方法的其他差异/用例/最佳做法/限制
    是什么?

  • 关于提供在 AssertionError 中的描述 - 如果它被提供或仅仅是事实,它是一个错误(和
    的断言类型)足以或多或少地确定在发现错误的情况下将提供堆栈跟踪


解决方案

我建议不要直接抛出 AssertionError 。如果您选择依赖 AssertionError 来检查不变量,前置/后置条件,状态等等,那么您仍然可以更好地使用-ea的常规断言标志也在生产中打开。

原因是断言机制(除了在编译器级别进行优化)让您有机会立即打开或关闭所有断言。即使你现在不能想到这样做的理由,如果你以后遇到一个原因,只要考虑你必须把所有的$ code抛出新的AssertionError(...) )类型代码,并且如果子句,则会以令人讨厌的环绕。你得到的图片。

正如你不想要一个魔术数字硬编码到你的代码的许多地方,并且可能会使用一个常量,你不应该感染你的代码与许多重复(即抛出新的AssertionError(...)部分)。



我相信你应该三思而行,然后依靠生产代码中的断言错误。原因是一个 AssertionError 非常通用。它有一个消息和一个原因,但实际上是这样的。

考虑使用具体的 RuntimeException 子类,这些子类将通过具体的课程更多地涉及到问题,以及携带与问题相关的实际数据。

作为一个简单的例子,考虑你在你的问题中提到的一个案例,你有一部分代码不期望到达。断言或 AssertionError 将传达一个事实,即您达到了一些意外的代码,但没有更多。使用特定的 RuntimeException 也可以在该时间点提供方法的局部变量和参数的状态。您可以认为,这可以通过设置断言消息或 AssertionError 来包含此信息,但是在使用自动错误日志记录/处理机制时不起作用。这种机制可以使用您用来检查意外行为的不同子类(code> RuntimeException

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.

For AssertionError, the exact opposite applies.

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
}

  • Is my reasoning correct?
  • What are the other differences/use cases/best practices/limitationsof 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 (andof assertion type) enough to be more or less sure that stack tracewill be provided in case of found bugs?

解决方案

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).

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和断言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 12:00