Java 断言
Java 断言
在本教程中,我们将借助示例了解 Java 断言语句(Java assertions)。
Java 中的断言通过测试我们假设为真的代码来帮助检测错误。
使用 assert
进行断言 关键字。
它的语法是:
assert condition;
这里,condition
是一个布尔表达式,我们在程序执行时假定它为真。
启用断言
默认情况下,断言在运行时被禁用和忽略。
要启用断言,我们使用:
java -ea:arguments
或
java -enableassertions:arguments
当断言启用且条件为 true
,程序正常执行。
但是如果条件计算为 false
启用断言时,JVM 抛出 AssertionError
,程序立即停止。
示例 1:Java 断言
class Main {
public static void main(String args[]) {
String[] weekends = {"Friday", "Saturday", "Sunday"};
assert weekends.length == 2;
System.out.println("There are " + weekends.length + " weekends in a week");
}
}
输出
There are 3 weekends in a week
我们得到上面的输出是因为这个程序没有编译错误,并且默认情况下,断言是禁用的。
启用断言后,我们得到以下输出:
Exception in thread "main" java.lang.AssertionError
另一种形式的断言语句
assert condition : expression;
在这种形式的断言语句中,一个表达式被传递给 AssertionError
的构造函数 目的。如果条件为 false
,此表达式的值将显示为错误的详细消息 .
详细消息用于捕获和传输断言失败的信息,以帮助调试问题。
示例 2:带有表达式示例的 Java 断言
class Main {
public static void main(String args[]) {
String[] weekends = {"Friday", "Saturday", "Sunday"};
assert weekends.length==2 : "There are only 2 weekends in a week";
System.out.println("There are " + weekends.length + " weekends in a week");
}
}
输出
Exception in thread "main" java.lang.AssertionError: There are only 2 weekends in a week
从上面的例子我们可以看出,表达式被传递给了 AssertionError
的构造函数 目的。如果我们的假设是 false
并启用断言,抛出异常并显示适当的消息。
此消息有助于诊断和修复导致断言失败的错误。
启用特定类和包的断言
如果我们不为断言命令行开关提供任何参数,
java -ea
这会在除系统类之外的所有类中启用断言。
我们还可以使用参数为特定的类和包启用断言。可以提供给这些命令行开关的参数是:
在类名中启用断言
要为我们程序 Main 的所有类启用断言,
java -ea Main
只启用一个类,
java -ea:AnimalClass Main
这仅在 AnimalClass
中启用断言 在 Main
程序。
在包名中启用断言
启用包 com.animal
的断言 仅及其子包,
java -ea:com.animal... Main
在未命名的包中启用断言
在当前工作目录中启用未命名包中的断言(当我们不使用包语句时)。
java -ea:... Main
在系统类中启用断言
为了在系统类中启用断言,我们使用不同的命令行开关:
java -esa:arguments
或
java -enablesystemassertions:arguments
可以提供给这些开关的参数是相同的。
禁用断言
要禁用断言,我们使用:
java -da arguments
或
java -disableassertions arguments
要在系统类中禁用断言,我们使用:
java -dsa:arguments
或
java -disablesystemassertions:arguments
禁用断言时可以传递的参数与启用断言时相同。
断言的优点
- 快速高效地检测和纠正错误。
- 断言检查仅在开发和测试期间进行。它们会在运行时自动从生产代码中删除,以免减慢程序的执行速度。
- 它有助于删除样板代码并使代码更具可读性。
- 重构和优化代码,增强对代码正常运行的信心。
何时使用断言
1。无法访问的代码
无法访问的代码是我们尝试运行程序时不执行的代码。使用断言来确保无法访问的代码实际上是无法访问的。
举个例子吧。
void unreachableCodeMethod() {
System.out.println("Reachable code");
return;
// Unreachable code
System.out.println("Unreachable code");
assert false;
}
让我们再举一个没有默认情况的 switch 语句的例子。
switch (dayOfWeek) {
case "Sunday":
System.out.println("It’s Sunday!");
break;
case "Monday":
System.out.println("It’s Monday!");
break;
case "Tuesday":
System.out.println("It’s Tuesday!");
break;
case "Wednesday":
System.out.println("It’s Wednesday!");
break;
case "Thursday":
System.out.println("It’s Thursday!");
break;
case "Friday":
System.out.println("It’s Friday!");
break;
case "Saturday":
System.out.println("It’s Saturday!");
break;
}
上面的 switch 语句表明一周中的天数只能是上述 7 个值之一。没有默认情况意味着程序员认为这些情况之一将始终被执行。
但是,在某些情况下,假设实际上是错误的,可能还没有考虑到。
应使用断言检查此假设,以确保未达到默认 switch case。
default:
assert false: dayofWeek + " is invalid day";
如果 dayOfWeek 有一个不是有效天数的值,一个 AssertionError
被抛出。
2。记录假设
为了记录他们的基本假设,许多程序员使用注释。举个例子吧。
if (i % 2 == 0) {
...
} else { // We know (i % 2 == 1)
...
}
改用断言。
随着程序的发展,评论可能会过时和不同步。但是,我们将被迫更新 assert
陈述;否则,它们也可能在有效条件下失败。
if (i % 2 == 0) {
...
} else {
assert i % 2 == 1 : i;
...
}
何时不使用断言
1。公共方法中的参数检查
公共方法中的参数可以由用户提供。
因此,如果使用断言来检查这些参数,则条件可能会失败并导致 AssertionError
.
与其使用断言,不如让它产生适当的运行时异常并处理这些异常。
2。评估影响程序操作的表达式
不要在断言条件下调用方法或评估以后会影响程序操作的异常。
让我们以列表 weekdays 为例 其中包含一周中所有日子的名称。
ArrayList<String> weekdays = new ArrayList<>(Arrays.asList("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ));
ArrayList<String> weekends= new ArrayList<>(Arrays.asList("Sunday", "Saturday" ));
assert weekdays.removeAll(weekends);
在这里,我们试图删除元素 Saturday
和 Sunday
来自 ArrayList weekdays .
如果启用了断言,则程序可以正常工作。但是,如果禁用断言,则不会删除列表中的元素。这可能会导致程序失败。
相反,将结果分配给一个变量,然后使用该变量进行断言。
ArrayList<String> weekdays = new ArrayList<>(Arrays.asList("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ));
ArrayList<String> weekends= new ArrayList<>(Arrays.asList("Sunday", "Saturday" ));
boolean weekendsRemoved = weekdays.removeAll(weekends);
assert weekendsRemoved;
这样,我们可以确保所有的周末 从 weekdays 中删除 无论断言是启用还是禁用。因此不影响以后的程序运行。
java