在 Java 中使用 AssertionError 和断言 [英] Using AssertionError and assertions in java
问题描述
我以标准方式在 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 anError
(and of assertion type) enough to be more or less sure that stack trace will be provided in case of found bugs?
推荐答案
我建议不要直接抛出 AssertionError
.如果您选择依赖 AssertionError
s 来检查不变量、前置/后置条件、状态条件等,你仍然最好使用常规断言,并在生产中打开-ea"标志作为好吧.
原因是断言机制(除了在编译器级别进行优化)让您有机会一次打开或关闭所有断言.即使你现在想不出这样做的理由,如果你将来遇到一个理由,只要考虑一下你必须检查所有的 throw new AssertionError(...)
键入代码并用一个讨厌的 if
子句将其包围.你得到了图片.
正如您不希望将幻数硬编码到代码中的许多地方,并且可能会使用常量代替,您不应该用许多重复来感染您的代码(即 throw new AssertionError(...)
部分).
I would advise against throwing AssertionError
s directly. If you choose to rely on AssertionError
s 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屋!