在编程中,`break`和`continue`语句在`switch`循环中扮演着跳出循环的角色。
1. `break`语句的应用:当`switch`循环执行到`break`时,会立即跳出当前的`switch`循环,并开始执行`switch`下面的语句。
例如,如果预设`switch`要执行10次,但第6次遇到`break`,则剩余的4次循环将不会被执行。
2. `continue`语句的应用:当在`switch`中执行到`continue`时,它会立即结束本次循环的剩余部分,并开始下一次循环。
同样以上例,当第6次遇到`continue`时,第6次循环会被跳过,直接进入第7次及以后的循环。
二、示例代码解读
第一段代码展示了如何在没有使用`break`或`continue`的情况下,`switch`语句的默认执行流程。而第二段代码则明确地使用了`break`来控制循环的次数。
```java
// 第一段代码(未使用break或continue)
int n=3;
switch(n) {
case 1: n=n+1; // 执行后n变为4
case 2: n+=2; // 接着n再增加2,变为6
case 3: n+=3; // 然后n再增加3,最终n=9
case 4: n+=4; // 最后n增加4,但此case未被break打断,继续执行
default: n+=1; // default部分再给n加1,最终输出n=11
printf("n=%d",n); // 输出结果n=11
// 第二段代码(使用了break)
int n=3;
switch(n) {
case 1: n=n+1; break; // 执行后n变为4,然后跳出该case
case 2: n+=2; break; // n再加2变为6,然后跳出该case
case 3: n+=3; break; // n再加3变为9,之后跳出整个switch块
// 其他case同理,每个case执行后都会因为break而跳出
default: n+=1; // 这里n再加1但由于之前的break,不会影响其他case的执行
printf("n=%d",n); // 输出结果n=6
```
三、assertion的功能与使用
J2SE 1.4引入了assertion功能,这是一种在程序开发中用于验证程序正确性的机制。尽管理论上可以通过assertion来证明程序的正确性,但实际操作中这通常是一项复杂且目前尚未广泛实践的任务。Assertion通常在程序中的一条语句中设置,用于检查一个boolean表达式的值。如果这个值为false,说明程序可能已经处于不正确的状态,系统将发出警告或停止运行。
在语法上,Java增加了关键字`assert`来支持assertion功能。其基本语法为:
```java
assert expression1; // 如果expression1为false,则抛出AssertionError
assert expression1:expression2; // 如果expression1为false,则用expression2的值构造AssertionError抛出
```
一、-ea和-da参数简介及作用机制
“-ea”和“-da”分别为Java中用于开启和关闭assertion功能的参数。它们的全名及缩写具有相同功能。这些参数用于控制Java程序中特定类和包的assertion功能。以下是参数的详细解释及其功能:
-ea(enable assertions):用于开启所有用户类的assertion功能。
-da(disable assertions):用于关闭所有用户类的assertion功能。
针对特定类或包,可以使用类似“-ea:MyClass1”或“-da:pkg1”的参数来开启或关闭特定类或包的assertion功能。
Java提供了几个API用于动态开启和关闭某些类和包的assertion功能。这些API包括在ClassLoader类中,如setDefaultAssertionStatus、setPackageAssertionStatus、setClassAssertionStatus和clearAssertionStatus等。它们分别用于全局开启/关闭、开启/关闭特定包或类的assertion功能,以及关闭所有assertion功能。
二、assertion设计的重要性及Java中的实现方式
Assertion机制在Java中非常重要,因为它允许程序员以统一的方式处理断言问题,提高代码的可读性和可维护性。如果没有断言机制,Java程序可能使用不同的方式进行检查,这可能会影响程序的性能。而语言层次的assertion支持可以将对性能的影响降到最低。
Java通过增强关键字“assert”来实现对assertion的支持,这表明Java认为assertion对于语言本身非常重要。与C语言通过Assert.h库实现断言支持不同,Java的assertion功能在运行时决定,而不是在编译时。这种设计使得目标代码更加灵活,但可能会因为assertion而牺牲一部分性能。
AssertionError作为Error的一个子类,表示非常关键的错误,这些错误通常不可恢复。程序员不应尝试对这些错误进行恢复。
三、assertion与继承的关系
在Java中,如果一个assert语句在父类中,当子类调用它时,该assert只在父类的assert开启时才会起作用。这说明assert语句不具有继承性。
四、assertion的使用场景及注意事项
Assertion通常用于检查对程序运行至关重要的值。这些值对整个程序或局部功能的完成有重大影响,且错误不易恢复。assertion的使用需谨慎考虑。assertion表达式应该简短易懂。如果需要评估复杂的表达式,应该使用函数进行计算。以下是一些使用assertion的示例:
在控制流中检查:在不应该发生的控制流上,可以使用assert false语句进行检查。
在私有函数计算前检查输入参数是否有效:对于私有函数,可以在函数开始处使用assert进行参数检查,确保输入满足特定条件。对于公共函数,通常不对无效的参数进行检查和处理,因为公共函数必须处理各种输入情况。私有函数的直接使用场景(如要求输入参数不为null)可以使用assertion进行检查。在函数执行后,我们需要验证其结果的有效性。对于一些计算函数,完成计算后,某些值需要满足特定属性。为此,我们可以使用assert语句进行检查。比如,我们有一个计算绝对值的函数,我们可以在函数的结果处增加一个断言,确保返回值大于等于零。
例如,如果一个函数旨在计算绝对值的函数,那么我们可以设置一个断言来保证其输出值始终大于等于零。这样,如果函数计算结果不符合预期,程序会抛出AssertionError。
我们还可以利用assert来检查程序中的不变量。这些不变量是在程序的整个生命周期中始终维持的值或状态。在关键的系统中,如财务系统,我们可以编写表达式来检查某些关键的不变量是否保持平衡。例如,公司的支出和收入之间的关系可以通过编写一个方法来检查,并在可能影响到这个平衡的方法前后使用assert进行验证。
值得注意的是,AssertionError是Error的子类,因此不能被捕获并处理。我们可以在程序中捕获这个异常并让程序继续执行。比如在一个名为AssertTest的类中,我们尝试调用一个带有断言的方法,如果断言失败则捕获AssertionError并打印出相关信息。然后程序可以继续执行并输出“go on”。但需要注意的是,Assert的使用不应滥用。在某些情况下,如检查参数是否为null或检查方法操作的返回值来判断方法操作的结果等场景并不适合使用assert。因为这些断言可能会被禁用而不执行相应的检查操作。因此在进行这些检查时最好使用显式的if语句或其他方式进行检查并抛出相应的异常。例如,如果检查list的removeAll操作是否成功时应该先用返回值判断然后才是断言操作避免断言被禁用带来的风险。