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".
看起来我从不在生产代码中使用断言,只在单元测试中看到断言。我知道在大多数情况下,我可以使用异常来执行上面的检查,但我想知道“专业”的适当方式。
11 个解决方案
#1
69
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.
请注意,如果(group!= null)不是断言,那只是一个条件。
#2
154
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 flaw 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.
断言的编写成本很低,几乎可以在任何地方使用它们而且我正在使用这个经验法则:断言语句看起来越愚蠢,它越有价值,嵌入的信息就越多。在调试不正常的程序时,您一定会根据您的经验检查更明显的故障可能性。然后你将检查那些不可能发生的问题:这正是断言有助于节省时间的时候。
#3
24
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 assert to see more cases where to use - or not to use - assert.
另外,您应该阅读有关assert的Oracle文章,以了解更多使用 - 或不使用 - 断言的情况。
#4
14
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.) - 使用断言进行内部一致性检查,如果有人将其关闭则根本不重要。 (注意,java命令默认关闭所有断言。)
- Use regular tests for any kind of checks what shouldn't be turned off. This includes defensive checks that guard against potential damage cause by bugs, and any validation data / requests / whatever provided by users or external services.
- 使用常规测试进行任何不应关闭的检查。这包括防御性检查,防止由于错误导致的潜在损害,以及任何验证数据/请求/用户或外部服务提供的任何内容。
The following code from your question is bad style and potentially 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 only the 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(尤其是不记录它),您将更难以诊断/调试问题,并可能允许应用程序造成更多损害。
#5
3
According to this doc http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#design-faq-general, "The assert statement is appropriate for nonpublic precondition, postcondition and class invariant checking. Public precondition checking should still be performed by checks inside methods that result in particular, documented exceptions, such as IllegalArgumentException and IllegalStateException."
根据这个文档http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#design-faq-general,, assert语句适用于非公共前置条件,后置条件和类不变量检查。公共前置条件检查仍应通过检查内部方法来执行,这些方法会导致特定的记录异常,例如IllegalArgumentException和IllegalStateException。“
If you want to know more about precondition, postcondition and class invariant, check this doc: http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#usage-conditions. It also contains with examples of assertions usage.
如果您想了解有关前置条件,后置条件和类不变量的更多信息,请查看以下文档:http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#usage-conditions。它还包含断言用法的示例。
#6
3
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.
好吧,回到微软,建议在你公开提供的所有API中抛出异常,并在你对内部代码做出的各种假设中使用Asserts。这是一个松散的定义但我想这取决于每个开发人员画线。
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.
我想结论是,每个应用程序都要向开发团队留下一些定义断言与异常的界限。
#7
1
Testing for null will only catch nulls causing problems, whereas a try/catch as you have it will catch any error.
测试null只会捕获导致问题的空值,而try / catch会捕获任何错误。
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代码可能会改变,你可能需要更大的网络。
#8
1
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.
您可以在使用时考虑这种简单的区别。异常将用于检查称为已检查和未检查错误的预期和意外错误,而断言主要用于运行时的调试目的,以查看假设是否经过验证。
#9
1
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) IllegalArgumentException which 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参数打开/关闭这些检查。通常情况下,我会一直保留这些检查,除非它们影响运行时性能或有类似的惩罚。
#10
1
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."
“一个好的经验法则是你应该对你想要忘记的特殊情况使用断言。断言是处理和忘记一个你不希望有的条件或状态的最快方法。处理。”
#11
0
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.
不幸的是,断言可以被禁用。在投入生产时,您需要在追踪无法预料的事情时获得所有帮助,因此断言会使自己失去资格。
#1
69
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.
请注意,如果(group!= null)不是断言,那只是一个条件。
#2
154
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 flaw 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.
断言的编写成本很低,几乎可以在任何地方使用它们而且我正在使用这个经验法则:断言语句看起来越愚蠢,它越有价值,嵌入的信息就越多。在调试不正常的程序时,您一定会根据您的经验检查更明显的故障可能性。然后你将检查那些不可能发生的问题:这正是断言有助于节省时间的时候。
#3
24
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 assert to see more cases where to use - or not to use - assert.
另外,您应该阅读有关assert的Oracle文章,以了解更多使用 - 或不使用 - 断言的情况。
#4
14
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.) - 使用断言进行内部一致性检查,如果有人将其关闭则根本不重要。 (注意,java命令默认关闭所有断言。)
- Use regular tests for any kind of checks what shouldn't be turned off. This includes defensive checks that guard against potential damage cause by bugs, and any validation data / requests / whatever provided by users or external services.
- 使用常规测试进行任何不应关闭的检查。这包括防御性检查,防止由于错误导致的潜在损害,以及任何验证数据/请求/用户或外部服务提供的任何内容。
The following code from your question is bad style and potentially 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 only the 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(尤其是不记录它),您将更难以诊断/调试问题,并可能允许应用程序造成更多损害。
#5
3
According to this doc http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#design-faq-general, "The assert statement is appropriate for nonpublic precondition, postcondition and class invariant checking. Public precondition checking should still be performed by checks inside methods that result in particular, documented exceptions, such as IllegalArgumentException and IllegalStateException."
根据这个文档http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#design-faq-general,, assert语句适用于非公共前置条件,后置条件和类不变量检查。公共前置条件检查仍应通过检查内部方法来执行,这些方法会导致特定的记录异常,例如IllegalArgumentException和IllegalStateException。“
If you want to know more about precondition, postcondition and class invariant, check this doc: http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#usage-conditions. It also contains with examples of assertions usage.
如果您想了解有关前置条件,后置条件和类不变量的更多信息,请查看以下文档:http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#usage-conditions。它还包含断言用法的示例。
#6
3
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.
好吧,回到微软,建议在你公开提供的所有API中抛出异常,并在你对内部代码做出的各种假设中使用Asserts。这是一个松散的定义但我想这取决于每个开发人员画线。
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.
我想结论是,每个应用程序都要向开发团队留下一些定义断言与异常的界限。
#7
1
Testing for null will only catch nulls causing problems, whereas a try/catch as you have it will catch any error.
测试null只会捕获导致问题的空值,而try / catch会捕获任何错误。
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代码可能会改变,你可能需要更大的网络。
#8
1
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.
您可以在使用时考虑这种简单的区别。异常将用于检查称为已检查和未检查错误的预期和意外错误,而断言主要用于运行时的调试目的,以查看假设是否经过验证。
#9
1
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) IllegalArgumentException which 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参数打开/关闭这些检查。通常情况下,我会一直保留这些检查,除非它们影响运行时性能或有类似的惩罚。
#10
1
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."
“一个好的经验法则是你应该对你想要忘记的特殊情况使用断言。断言是处理和忘记一个你不希望有的条件或状态的最快方法。处理。”
#11
0
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.
不幸的是,断言可以被禁用。在投入生产时,您需要在追踪无法预料的事情时获得所有帮助,因此断言会使自己失去资格。