Java 何时使用断言,何时使用异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1957645/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to use an assertion and when to use an exception
提问by cometta
Most of the time I will use an exception to check for a condition in my code, I wonder when it is an appropriate time to use an assertion?
大多数时候我会使用异常来检查代码中的条件,我想知道什么时候使用断言合适?
For instance,
例如,
Group group=null;
try{
group = service().getGroup("abc");
}catch(Exception e){
//I dont log error because I know whenever error occur mean group not found
}
if(group !=null)
{
//do something
}
Could you indicate how an assertion fits in here? Should I use an assertion?
你能指出一个断言在这里是如何适应的吗?我应该使用断言吗?
It seems like I never use assertions in production code and only see assertions in unit tests. I do know that in most cases, I can just use exception to do the checking like above, but I want to know appropriate way to do it "professionally".
似乎我从不在生产代码中使用断言,只在单元测试中看到断言。我确实知道在大多数情况下,我可以使用异常来进行上述检查,但我想知道“专业地”执行此操作的适当方法。
采纳答案by Marius
Assertions should be used to check something that should never happen, while an exception should be used to check something that might happen.
断言应该用于检查不应该发生的事情,而异常应该用于检查可能发生的事情。
For example, a function might divide by 0, so an exception should be used, but an assertion could be used to check that the harddrive suddenly disappears.
例如,一个函数可能被 0 除,因此应该使用异常,但可以使用断言来检查硬盘驱动器是否突然消失。
An assertion would stop the program from running, but an exception would let the program continue running.
断言会阻止程序运行,但异常会让程序继续运行。
Note that if(group != null)
is not an assertion, that is just a conditional.
请注意,这if(group != null)
不是断言,这只是一个条件。
回答by Gregory Pakosz
Out of my mind (list may be incomplete, and is too long to fit in a comment), I would say:
我想不通(列表可能不完整,而且太长而无法发表评论),我会说:
- use exceptions when checking parameters passed to public or protected methods and constructors
- use exceptions when interacting with the user or when you expect the client code to recover from an exceptional situation
- use exceptions to address problems that might occur
- use assertions when checking pre-conditions, post-conditions and invariants of private/internal code
- use assertions to provide feedback to yourself or your developer team
- use assertions when checking for things that are very unlikely to happen otherwise it means that there is a serious ?aw in your application
- use assertions to state things that you (supposedly) know to be true
- 检查传递给公共或受保护方法和构造函数的参数时使用异常
- 在与用户交互时或当您希望客户端代码从异常情况中恢复时使用异常
- 使用异常来解决可能发生的问题
- 在检查私有/内部代码的前置条件、后置条件和不变量时使用断言
- 使用断言向您自己或您的开发团队提供反馈
- 在检查不太可能发生的事情时使用断言,否则意味着您的应用程序中存在严重错误
- 使用断言来陈述你(据说)知道是真的事情
In other words, exceptions address the robustness of your application while assertions address its correctness.
换句话说,异常解决了应用程序的健壮性,而断言解决了它的正确性。
Assertions are designed to be cheap to write, you can use them almost everywhere and I'm using this rule of thumb: the more an assertion statement looks stupid, the more valuable it is and the more information it embeds. When debugging a program that does not behave the right way, you will surely check the more obvious failure possibilities based on your experience. Then you will check for problems that just cannot happen: this is exactly when assertions help a lot and save time.
断言的设计成本很低,你几乎可以在任何地方使用它们,我正在使用这个经验法则:断言语句看起来越愚蠢,它就越有价值,它嵌入的信息也越多。在调试行为不正确的程序时,您肯定会根据自己的经验检查更明显的失败可能性。然后,您将检查不可能发生的问题:这正是断言有很大帮助并节省时间的时候。
回答by Phil H
Testing for null will only catch nulls causing problems, whereas a try/catch as you have it will catch anyerror.
测试空值只会捕获导致问题的空值,而尝试/捕获它会捕获任何错误。
Broadly, try/catch is safer, but slightly slower, and you have to be careful that you catch all the kinds of error that may occur. So I would say use try/catch - one day the getGroup code may change, and you just might need that bigger net.
从广义上讲,try/catch 更安全,但速度稍慢,您必须小心捕捉可能发生的所有类型的错误。所以我会说使用 try/catch - 有一天 getGroup 代码可能会改变,你可能只需要更大的网络。
回答by chburd
Remember assertions can be disabled at runtime using parameters, and are disabled by default, so don't count on them except for debugging purposes.
请记住,可以在运行时使用参数禁用断言,并且默认情况下禁用断言,因此除了调试目的外,不要指望它们。
Also you should read the Oracle article about assertto see more cases where to use - or not to use - assert.
此外,您应该阅读有关断言的Oracle 文章,以了解更多使用或不使用断言的情况。
回答by rui
Well, back at Microsoft, the recommendation was to throw Exceptions in all APIs you make available publicly and use Asserts in all sorts of assumptions you make about code that's internal. It's a bit of a loose definition but I guess it's up to each developer to draw the line.
好吧,回到 Microsoft,建议是在您公开提供的所有 API 中抛出异常,并在您对内部代码做出的各种假设中使用断言。这是一个有点松散的定义,但我想这取决于每个开发人员来划清界限。
Regarding the use of Exceptions, as the name says, their usage should be exceptional so for the code you present above, the getGroup
call should return null
if no service exists. Exception should only occur if a network link goes down or something like that.
关于异常的使用,顾名思义,它们的使用应该是特殊的,因此对于您上面提供的代码,如果不存在服务,getGroup
调用应该返回null
。仅当网络链接出现故障或类似情况时才会发生异常。
I guess the conclusion is that it's a bit left down to the development team for each application to define the boundaries of assert vs exceptions.
我想结论是每个应用程序的开发团队都需要定义断言与异常的边界。
回答by Brian Agnew
I confess I'm a little confused by your question. When an assertion condition is not met, an exception is thrown. Confusingly this is called AssertionError. Note that it's unchecked, like (for example) IllegalArgumentExceptionwhich is thrown in very similar circumstances.
我承认我对你的问题有点困惑。当不满足断言条件时,抛出异常。令人困惑的是,这称为AssertionError。请注意,它是未经检查的,例如(例如)在非常相似的情况下抛出的IllegalArgumentException。
So using assertions in Java
所以在 Java 中使用断言
- is a more concise means of writing a condition/throw block
- permits you to turn these checks on/off via JVM parameters. Normally I would leave these checks on all the time, unless they impact runtime performance or have a similar penalty.
- 是一种更简洁的编写条件/抛出块的方法
- 允许您通过 JVM 参数打开/关闭这些检查。通常我会一直保留这些检查,除非它们影响运行时性能或有类似的惩罚。
回答by Thorbj?rn Ravn Andersen
Unfortunately asserts can be disabled. When in production you need all the help you can get when tracking down something unforeseen, so asserts disqualify themselves.
不幸的是,断言可以被禁用。在生产过程中,您需要在跟踪不可预见的事情时获得的所有帮助,因此断言会取消自己的资格。
回答by Stephen C
As a general rule:
作为基本规则:
- Use assertions for internal consistency checks where it doesn't matter at all if someone turns them off. (Note that the
java
command turns off all assertions by default.) - Use regular tests for any kind of checks what shouldn't be turned off. This includesdefensive checks that guard against potential damage cause by bugs, and any validation data / requests / whatever provided by users or external services.
- 使用断言进行内部一致性检查,如果有人将其关闭则根本无关紧要。(请注意,该
java
命令默认关闭所有断言。) - 使用定期测试来检查不应该关闭的任何类型。这包括防御性检查,以防止错误造成的潜在损害,以及任何验证数据/请求/用户或外部服务提供的任何内容。
The following code from your question is bad style andpotentially buggy
您问题中的以下代码风格不佳且可能有问题
try {
group = service().getGroup("abc");
} catch (Exception e) {
//i dont log error because i know whenever error occur mean group not found
}
The problem is that you DON'T know that an exception means that the group was not found. It is also possible that the service()
call threw an exception, or that it returned null
which then caused a NullPointerException
.
问题是您不知道异常意味着未找到该组。service()
调用也有可能抛出异常,或者它返回null
导致NullPointerException
.
When you catch an "expected" exception, you should catch onlythe exception that you are expecting. By catching java.lang.Exception
(and especially by not logging it), you are making it harder to diagnose / debug the problem, and potentially allowing the app to do more damage.
当您捕获“预期”异常时,您应该只捕获您预期的异常。通过捕获java.lang.Exception
(尤其是不记录它),您会使诊断/调试问题变得更加困难,并可能使应用程序造成更大的破坏。
回答by SBTec
You can use this simple difference in mind while their usage. Exceptions will be used for checking expected and unexpected errors called checked and unchecked error while assertion is used mainly for debugging purposes at the run time to see whether the assumptions are validated or not.
您可以在使用它们时记住这个简单的区别。异常将用于检查预期和意外的错误,称为检查和未检查错误,而断言主要用于运行时的调试目的,以查看假设是否得到验证。
回答by Phil
See section 6.1.2 (Assertions vs. other error code) of Sun's documentation at the following link.
请参阅以下链接中 Sun 文档的第 6.1.2 节(断言与其他错误代码)。
http://www.oracle.com/technetwork/articles/javase/javapch06.pdf
http://www.oracle.com/technetwork/articles/javase/javapch06.pdf
This document gives the best advice I've seen on when to use assertions. Quoting from the document:
本文档提供了我所见过的关于何时使用断言的最佳建议。引用文档:
"A good rule of thumb is that you should use an assertion for exceptional cases that you would like to forget about. An assertion is the quickest way to deal with, and forget, a condition or state that you don't expect to have to deal with."
“一个好的经验法则是,你应该在你想忘记的特殊情况下使用断言。断言是处理和忘记你不希望必须这样做的条件或状态的最快方法处理。”