Java 断言(Assert)

在本教程中,我们将借助示例学习Java assert语句(Java断言)。

Java中的断言通过测试我们认为是正确的代码来帮助检测错误。

使用assert关键字进行断言。

其语法为:

assertcondition;

这里condition是一个布尔表达式,我们假定在程序执行时为真。

启用断言

默认情况下,断言在运行时被禁用并被忽略。

为了启用断言,我们使用:

java-ea:arguments

或者

java-enableassertions:arguments

启用断言且条件为时true,程序将正常执行。

但是,如果在启用断言时条件计算为false, JVM会抛出AssertionError,程序会立即停止。

示例1:Java 断言

classMain{publicstaticvoidmain(Stringargs[]){String[]weekends={"Friday","Saturday","Sunday"};assertweekends.length==2;System.out.println("这个星期有"+weekends.length+"个周末");}}

输出结果

这个星期有3个周末

我们得到上面的输出,因为该程序没有编译错误,并且默认情况下,断言被禁用。

启用断言后,我们得到以下输出:

Exceptioninthread"main"java.lang.AssertionError

断言的另一种形式声明

assertcondition:expression;

在这种形式的断言语句中,将表达式传递到AssertionError对象的构造函数。 如果条件为false,则该表达式的值显示为错误的详细信息。

详细消息用于捕获和传输断言失败的信息,以帮助调试问题。

示例2:带有表达式Java断言示例

classMain{publicstaticvoidmain(Stringargs[]){String[]weekends={"Friday","Saturday","Sunday"};assertweekends.length==2:"Thereareonly2weekendsinaweek";System.out.println("Thereare"+weekends.length+"weekendsinaweek");}}

输出结果

Exceptioninthread"main"java.lang.AssertionError:Thereareonly2weekendsinaweek

从上面的示例可以看出,表达式被传递给AssertionError对象的构造函数。如果我们的假设是正确的false,并且启用了断言,则会抛出异常并显示一条适当的消息。

此消息有助于诊断和修复导致断言失败的错误。

为特定的类和包启用断言

如果我们不向断言命令行开关提供任何参数,

java-ea

这将在除系统类之外的所有类中启用断言。

我们还可以使用参数为特定的类和包启用断言。 可以提供给这些命令行开关的参数为:

在类名中启用断言

为了对程序Main的所有类启用断言,

java-eaMain

只启用一个类,

java-ea:AnimalClassMain

这只允许在Main程序的AnimalClass中使用断言。

在包名称中启用断言

要对包com.animal及其子包启用断言

java-ea:com.animal...Main

在未命名的包中启用断言

在当前工作目录中的未命名包中启用断言(当我们不使用package语句时)。

java-ea:...Main

在系统类中启用断言

为了在系统类中启用断言,我们使用不同的命令行开关:

java-esa:arguments

java-enablesystemassertions:arguments

可以提供给这些开关的参数是相同的。

禁用断言

要禁用断言,我们使用:

java-daarguments

java-disableassertionsarguments

要在系统类中禁用断言,我们使用:

java-dsa:arguments

java-disablesystemassertions:arguments

禁用断言时可以传递的参数与启用断言时相同。

断言的优点

  1. 快速高效地检测和纠正错误。

  2. 断言检查仅在开发和测试期间进行。它们会在运行时自动在生产代码中删除,因此不会减慢程序的执行速度。

  3. 它有助于删除样板代码并使代码更具可读性。

  4. 重构和优化代码,以增强其正确运行的信心。

何时使用断言

1.无法访问的代码

无法访问的代码是我们尝试运行该程序时不会执行的代码。使用断言来确保无法访问的代码实际上是无法访问的。

让我们举个实例。

voidunreachableCodeMethod(){System.out.println("Reachablecode");return;//UnreachablecodeSystem.out.println("Unreachablecode");assertfalse;}

让我们再来看一个没有默认情况的switch语句示例。

switch(dayOfWeek){case"Sunday":System.out.println("It’sSunday!");break;case"Monday":System.out.println("It’sMonday!");break;case"Tuesday":System.out.println("It’sTuesday!");break;case"Wednesday":System.out.println("It’sWednesday!");break;case"Thursday":System.out.println("It’sThursday!");break;case"Friday":System.out.println("It’sFriday!");break;case"Saturday":System.out.println("It’sSaturday!");break;}

上面的switch语句表明,一周中的天数只能是以上7个值中的一个。没有默认情况意味着程序员相信这些情况中的一个将始终被执行。

但是,在某些假设实际上是错误的情况下,可能尚未考虑某些情况。

应该使用断言来检查此假设,以确保未达到默认switch条件。

default:assertfalse:dayofWeek+"isinvalidday";

如果dayOfWeek其值不是有效日期,则抛出AssertionError。

2.记录假设

为了记录其基本假设,许多程序员使用注释。让我们举个实例。

if(i%2==0){...}else{//Weknow(i%2==1)...}

请改用断言。

随着程序的增长,注释可能会过时和不同步。 但是,我们将不得不更新assert语句; 否则,它们也可能因有效条件而失败。

if(i%2==0){...}else{asserti%2==1:i;...}

什么时候不使用断言

1.公共方法中的参数检查

用户可以提供公共方法中的参数。

因此,如果使用断言来检查这些参数,则条件可能会失败并导致AssertionError。

与其使用断言,不如让它产生适当的运行时异常并处理这些异常。

2.对影响程序操作的表达式求值

不要调用方法或评估可能在断言条件下影响程序操作的异常。

让我们以一个列表示例为例,weekdays列表包含一周中所有天的名称。

ArrayList<String>weekdays=newArrayList<>(Arrays.asList("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"));ArrayList<String>weekends=newArrayList<>(Arrays.asList("Sunday","Saturday"));assertweekdays.removeAll(weekends);

在这里,我们试图从ArrayList weekdays中删除元素Saturday和Sunday。

如果启用了断言,则程序可以正常运行。但是,如果禁用了断言,则不会删除列表中的元素。这可能会导致程序失败。

而是将结果分配给变量,然后使用该变量进行断言。

ArrayList<String>weekdays=newArrayList<>(Arrays.asList("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"));ArrayList<String>weekends=newArrayList<>(Arrays.asList("Sunday","Saturday"));booleanweekendsRemoved=weekdays.removeAll(weekends);assertweekendsRemoved;

这样,我们可以确保从weekdays中删除所有weekends,而不考虑启用或禁用断言。 结果,它不会影响将来的程序操作。

编辑于2024-05-20 12:11