Java assert 关键字有什么作用,应该在什么时候使用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2758224/
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
What does the Java assert keyword do, and when should it be used?
提问by Praveen
What are some real life examplesto understand the key role of assertions?
有哪些现实生活中的例子可以理解断言的关键作用?
采纳答案by Ophidian
Assertions(by way of the assertkeyword) were added in Java 1.4. They are used to verify the correctness of an invariant in the code. They should never be triggered in production code, and are indicative of a bug or misuse of a code path. They can be activated at run-time by way of the -ea
option on the java
command, but are not turned on by default.
Java 1.4 中添加了断言(通过assert关键字)。它们用于验证代码中不变量的正确性。它们永远不应该在生产代码中被触发,并且表示代码路径存在错误或误用。它们可以在运行时通过命令-ea
上的选项激活java
,但默认情况下不会打开。
An example:
一个例子:
public Foo acquireFoo(int id) {
Foo result = null;
if (id > 50) {
result = fooService.read(id);
} else {
result = new Foo(id);
}
assert result != null;
return result;
}
回答by Bj?rn
A real world example, from a Stack-class (from Assertion in Java Articles)
一个真实世界的例子,来自 Stack 类(来自Java 文章中的断言)
public int pop() {
// precondition
assert !isEmpty() : "Stack is empty";
return stack[--num];
}
回答by Donal Fellows
Assertions are used to check post-conditions and "should never fail" pre-conditions. Correct code should never fail an assertion; when they trigger, they should indicate a bug (hopefully at a place that is close to where the actual locus of the problem is).
断言用于检查后置条件和“不应失败”的前置条件。正确的代码永远不应该使断言失败;当它们触发时,它们应该指出一个错误(希望在靠近问题实际位置的地方)。
An example of an assertion might be to check that a particular group of methods is called in the right order (e.g., that hasNext()
is called before next()
in an Iterator
).
断言的一个例子可能是检查的方法的具体基团是所谓的正确的顺序(例如,hasNext()
被称为前next()
在Iterator
)。
回答by SBTec
Assertion are basically used to debug the application or it is used in replacement of exception handling for some application to check the validity of an application.
断言主要用于调试应用程序或用于替代某些应用程序的异常处理以检查应用程序的有效性。
Assertion works at run time. A simple example, that can explain the whole concept very simply, is herein - What does the assert keyword do in Java?(WikiAnswers).
断言在运行时起作用。一个简单的例子,可以非常简单地解释整个概念,在这里 - assert 关键字在 Java 中有什么作用?(维基答案)。
回答by pavani
assert
is a keyword. It was introduced in JDK 1.4. The are two types of assert
s
assert
是关键字。它是在 JDK 1.4 中引入的。有两种类型的assert
s
- Very simple
assert
statements - Simple
assert
statements.
- 很简单的
assert
说法 - 简单的
assert
陈述。
By default all assert
statements will not be executed. If an assert
statement receives false, then it will automatically raise an assertion error.
默认情况下,assert
不会执行所有语句。如果一个assert
语句接收到 false,那么它会自动引发一个断言错误。
回答by TwoThe
Let's assume that you are supposed to write a program to control a nuclear power-plant. It is pretty obvious that even the most minor mistake could have catastrophic results, therefore your code has to bebug-free (assuming that the JVM is bug-free for the sake of the argument).
让我们假设您应该编写一个程序来控制核电站。很明显,即使是最轻微的错误也可能导致灾难性的结果,因此您的代码必须没有错误(为了争论,假设 JVM 没有错误)。
Java is not a verifiable language, which means: you cannot calculate that the result of your operation will be perfect. The main reason for this are pointers: they can point anywhere or nowhere, therefore they cannot be calculated to be of this exact value, at least not within a reasonable span of code. Given this problem, there is no way to prove that your code is correct at a whole. But what you can do is to prove that you at least find every bug when it happens.
Java 不是一种可验证的语言,这意味着:您无法计算出您的操作结果会是完美的。造成这种情况的主要原因是指针:它们可以指向任何地方或任何地方,因此它们不能被计算为这个确切的值,至少不能在合理的代码范围内。鉴于此问题,无法证明您的代码整体上是正确的。但是你能做的就是证明你至少在每一个 bug 发生时都能找到它。
This idea is based on the Design-by-Contract(DbC) paradigm: you first define (with mathematical precision) what your method is supposed to do, and then verify this by testing it during actual execution. Example:
这个想法基于合同设计(DbC) 范式:您首先定义(以数学精度)您的方法应该做什么,然后通过在实际执行期间对其进行测试来验证这一点。例子:
// Calculates the sum of a (int) + b (int) and returns the result (int).
int sum(int a, int b) {
return a + b;
}
While this is pretty obvious to work fine, most programmers will not see the hidden bug inside this one (hint: the Ariane V crashed because of a similar bug). Now DbC defines that you must alwayscheck the input and output of a function to verify that it worked correctly. Java can do this through assertions:
虽然这很明显可以正常工作,但大多数程序员不会看到这个隐藏的错误(提示:Ariane V 因类似的错误而崩溃)。现在 DbC 定义您必须始终检查函数的输入和输出以验证它是否正常工作。Java 可以通过断言来做到这一点:
// Calculates the sum of a (int) + b (int) and returns the result (int).
int sum(int a, int b) {
assert (Integer.MAX_VALUE - a >= b) : "Value of " + a + " + " + b + " is too large to add.";
final int result = a + b;
assert (result - a == b) : "Sum of " + a + " + " + b + " returned wrong sum " + result;
return result;
}
Should this function now ever fail, you will notice it. You will know that there is a problem in your code, you know where it is and you know what caused it (similar to Exceptions). And what is even more important: you stop executing right when it happens to prevent any further code to work with wrong values and potentially cause damage to whatever it controls.
如果此功能现在失败,您会注意到它。你会知道你的代码有问题,你知道它在哪里,你知道是什么导致了它(类似于异常)。更重要的是:当它碰巧阻止任何进一步的代码使用错误的值并可能对其控制的任何内容造成损害时,您停止执行。
Java Exceptions are a similar concept, but they fail to verify everything. If you want even more checks (at the cost of execution speed) you need to use assertions. Doing so will bloat your code, but you can in the end deliver a product at a surprisingly short development time (the earlier you fix a bug, the lower the cost). And in addition: if there is any bug inside your code, you will detect it. There is no way of a bug slipping-through and cause issues later.
Java 异常是一个类似的概念,但它们无法验证所有内容。如果您想要更多检查(以执行速度为代价),您需要使用断言。这样做会使您的代码膨胀,但最终您可以在极短的开发时间内交付产品(越早修复错误,成本越低)。此外:如果您的代码中有任何错误,您将检测到它。没有办法让错误溜走并在以后引起问题。
This still is not a guarantee for bug-free code, but it is much closer to that, than usual programs.
这仍然不能保证代码没有错误,但它比通常的程序更接近这一点。
回答by MiguelMunoz
Here's the most common use case. Suppose you're switching on an enum value:
这是最常见的用例。假设您要打开一个枚举值:
switch (fruit) {
case apple:
// do something
break;
case pear:
// do something
break;
case banana:
// do something
break;
}
As long as you handle every case, you're fine. But someday, somebody will add fig to your enum and forget to add it to your switch statement. This produces a bug that may get tricky to catch, because the effects won't be felt until after you've left the switch statement. But if you write your switch like this, you can catch it immediately:
只要你处理每一种情况,你就没事。但总有一天,有人会将 fig 添加到您的枚举中,而忘记将其添加到您的 switch 语句中。这会产生一个可能难以捕捉的错误,因为在您离开 switch 语句之后才会感受到效果。但是如果你这样写你的开关,你可以立即抓住它:
switch (fruit) {
case apple:
// do something
break;
case pear:
// do something
break;
case banana:
// do something
break;
default:
assert false : "Missing enum value: " + fruit;
}
回答by MiguelMunoz
Assertions are a development-phase tool to catch bugs in your code. They're designed to be easily removed, so they won't exist in production code. So assertions are not part of the "solution" that you deliver to the customer. They're internal checks to make sure that the assumptions you're making are correct. The most common example is to test for null. Many methods are written like this:
断言是一个开发阶段的工具,用于捕获代码中的错误。它们被设计为易于删除,因此它们不会存在于生产代码中。因此,断言不是您交付给客户的“解决方案”的一部分。它们是内部检查,以确保您所做的假设是正确的。最常见的例子是测试是否为空。很多方法都是这样写的:
void doSomething(Widget widget) {
if (widget != null) {
widget.someMethod(); // ...
... // do more stuff with this widget
}
}
Very often in a method like this, the widget should simply never be null. So if it's null, there's a bug in your code somewhere that you need to track down. But the code above will never tell you this. So in a well-intentioned effort to write "safe" code, you're also hiding a bug. It's much better to write code like this:
通常在这样的方法中,小部件应该永远不会为空。因此,如果它为空,则您的代码中存在需要追踪的错误。但是上面的代码永远不会告诉你这一点。因此,在编写“安全”代码的善意努力中,您也隐藏了一个错误。写这样的代码要好得多:
/**
* @param Widget widget Should never be null
*/
void doSomething(Widget widget) {
assert widget != null;
widget.someMethod(); // ...
... // do more stuff with this widget
}
This way, you will be sure to catch this bug early. (It's also useful to specify in the contract that this parameter should never be null.) Be sure to turn assertions on when you test your code during development. (And persuading your colleagues to do this, too is often difficult, which I find very annoying.)
这样,您一定会及早发现此错误。(在合同中指定此参数永远不应为空也很有用。)在开发期间测试代码时,请务必打开断言。(说服你的同事这样做也常常很困难,我觉得这很烦人。)
Now, some of your colleagues will object to this code, arguing that you should still put in the null check to prevent an exception in production. In that case, the assertion is still useful. You can write it like this:
现在,您的一些同事会反对此代码,认为您仍应进行空检查以防止生产中出现异常。在这种情况下,断言仍然有用。你可以这样写:
void doSomething(Widget widget) {
assert widget != null;
if (widget != null) {
widget.someMethod(); // ...
... // do more stuff with this widget
}
}
This way, your colleagues will be happy that the null check is there for production code, but during development, you're no longer hiding the bug when widget is null.
这样,您的同事会很高兴对生产代码进行空检查,但在开发过程中,当小部件为空时,您不再隐藏错误。
Here's a real-world example: I once wrote a method that compared two arbitrary values for equality, where either value could be null:
这是一个真实世界的例子:我曾经写过一个方法来比较两个任意值的相等性,其中任何一个值都可以为空:
/**
* Compare two values using equals(), after checking for null.
* @param thisValue (may be null)
* @param otherValue (may be null)
* @return True if they are both null or if equals() returns true
*/
public static boolean compare(final Object thisValue, final Object otherValue) {
boolean result;
if (thisValue == null) {
result = otherValue == null;
} else {
result = thisValue.equals(otherValue);
}
return result;
}
This code delegates the work of the equals()
method in the case where thisValue is not null. But it assumes the equals()
method correctly fulfills the contract of equals()
by properly handling a null parameter.
此代码equals()
在 thisValue 不为空的情况下委托方法的工作。但它假定该equals()
方法equals()
通过正确处理空参数来正确履行合同。
A colleague objected to my code, telling me that many of our classes have buggy equals()
methods that don't test for null, so I should put that check into this method. It's debatable if this is wise, or if we should force the error, so we can spot it and fix it, but I deferred to my colleague and put in a null check, which I've marked with a comment:
一位同事反对我的代码,告诉我我们的许多类都有equals()
不测试 null 的错误方法,所以我应该把这个检查放到这个方法中。如果这是明智的,或者我们是否应该强制错误,那么我们可以发现它并修复它,这是有争议的,但我推迟了我的同事并进行了空检查,我已经用评论标记了它:
public static boolean compare(final Object thisValue, final Object otherValue) {
boolean result;
if (thisValue == null) {
result = otherValue == null;
} else {
result = otherValue != null && thisValue.equals(otherValue); // questionable null check
}
return result;
}
The additional check here, other != null
, is only necessary if the equals()
method fails to check for null as required by its contract.
此处的额外检查other != null
仅在该equals()
方法未能按照合同要求检查 null时才需要。
Rather than engage in a fruitless debate with my colleague about the wisdom of letting the buggy code stay in our code base, I simply put two assertions in the code. These assertions will let me know, during the development phase, if one of our classes fails to implement equals()
properly, so I can fix it:
与其与我的同事就让有缺陷的代码留在我们的代码库中是否明智进行无谓的辩论,我只是在代码中加入了两个断言。这些断言会让我知道,在开发阶段,如果我们的一个类无法equals()
正确实现,我可以修复它:
public static boolean compare(final Object thisValue, final Object otherValue) {
boolean result;
if (thisValue == null) {
result = otherValue == null;
assert otherValue == null || otherValue.equals(null) == false;
} else {
result = otherValue != null && thisValue.equals(otherValue);
assert thisValue.equals(null) == false;
}
return result;
}
The important points to keep in mind are these:
要记住的要点是:
Assertions are development-phase tools only.
The point of an assertion is to let you know if there's a bug, not just in your code, but in your code base. (The assertions here will actually flag bugs in other classes.)
Even if my colleague was confident that our classes were properly written, the assertions here would still be useful. New classes will be added that might fail to test for null, and this method can flag those bugs for us.
In development, you should always turn assertions on, even if the code you've written doesn't use assertions. My IDE is set to always do this by default for any new executable.
The assertions don't change the behavior of the code in production, so my colleague is happy that the null check is there, and that this method will execute properly even if the
equals()
method is buggy. I'm happy because I will catch any buggyequals()
method in development.
断言只是开发阶段的工具。
断言的重点是让您知道是否存在错误,不仅在您的代码中,而且在您的代码库中。(这里的断言实际上会标记其他类中的错误。)
即使我的同事确信我们的类编写正确,这里的断言仍然有用。将添加可能无法测试 null 的新类,此方法可以为我们标记这些错误。
在开发中,您应该始终打开断言,即使您编写的代码不使用断言。默认情况下,我的 IDE 设置为始终为任何新的可执行文件执行此操作。
断言不会改变生产中代码的行为,所以我的同事很高兴有空检查,即使方法有问题,这个方法也能正确执行
equals()
。我很高兴,因为我会发现equals()
开发中的任何错误方法。
Also, you should test your assertion policy by putting in a temporary assertion that will fail, so you can be certain that you are notified, either through the log file or a stack trace in the output stream.
此外,您应该通过放入一个会失败的临时断言来测试您的断言策略,这样您就可以确定您会收到通知,无论是通过日志文件还是输出流中的堆栈跟踪。
回答by John White
Assert is veryuseful when developing. You use it when something just cannothappen if your code is working correctly. It's easy to use, and can stay in the code for ever, because it will be turned off in real life.
Assert在开发时非常有用。如果您的代码工作正常,则在某些事情不会发生时使用它。它易于使用,并且可以永远留在代码中,因为它会在现实生活中被关闭。
If there is any chance that the condition can occur in real life, then you must handle it.
如果这种情况有可能在现实生活中发生,那么您必须处理它。
I love it, but don't know how to turn it on in Eclipse/Android/ADT . It seems to be off even when debugging. (There is a thread on this, but it refers to the 'Java vm', which does not appear in the ADT Run Configuration).
我喜欢它,但不知道如何在 Eclipse/Android/ADT 中打开它。即使在调试时它似乎也关闭了。(这里有一个线程,但它指的是“Java vm”,它没有出现在 ADT 运行配置中)。
回答by John White
Basically, "assert true" will pass and "assert false" will fail. Let's looks at how this will work:
基本上,“assert true”会通过而“assert false”会失败。让我们看看这将如何工作:
public static void main(String[] args)
{
String s1 = "Hello";
assert checkInteger(s1);
}
private static boolean checkInteger(String s)
{
try {
Integer.parseInt(s);
return true;
}
catch(Exception e)
{
return false;
}
}