流程控制
分支控制
在Java语言中,提供了两种常见的分支控制结构:
- if 条件语句
- switch 语句
if 条件语句
if 语句使用布尔值或者布尔值表达式来做流程控制,主要表现为两种形式:
仅有 if 判断
javaif( 布尔返回值的条件 ) { // 条件符合的业务逻辑 }
// 如下示例,if判断就不会执行
javaint age = 10; if(age > 18) { System.out.println("成年人"); }
if else 判断
javaif( 布尔返回值的条件 ) { // 条件符合的业务逻辑 }else{ // 条件不符的业务逻辑 }
// 如下示例,控制台会输出“未成年”
javaint age = 10; if(age > 18) { System.out.println("成年人"); // 由于条件不符合,这段代码不会执行 }else { System.out.println("未成年"); // 会执行这段代码 }
多 if 条件判断
多 if 条件时,会从上往下逐个判断,只要其中一个满足条件,就不会再执行其他判断,包括else;
javaif( 布尔返回值的条件1 ){ // 条件1符合的业务逻辑 }else if( 布尔返回值的条件2 ){ // 条件2符合的业务逻辑 }else{ // 条件都不符的业务逻辑 }
javaint age = 30; if(age > 0 && age < 18) { System.out.println("未成年"); // 条件不符合,不执行 }else if(age >= 18 && age < 60) { System.out.println("成年人"); // 条件符合,输出 }else if(age >= 60 && age < 120) { System.out.println("老年人"); // 前面if已经匹配上,不执行 }else{ // else 可不写 System.out.println("年龄有误"); // 所有if条件都不满足的情况下,才执行else }
多重选择:switch 语句
switch 语句用于表达式匹配多个值的流程控制;类似与多 if 条件判断,只是多if判断显的非常的冗余、臃肿;那么使用switch 语句就会比较清晰; 而且,if条件只能是返回值为布尔类型(boolean)的表达式,但是 switch 语句中,case支持的类型就比较丰富:
- 类型为char、byte、short、int的常量表达式
- 枚举类型
- 字符串字面量
- 多个字符串使用
,
分隔(JDK 12 之后)
switch( 表达式 ){
case 值1:
// 符合结果的业务逻辑
break;
case 值2:
// 符合结果的业务逻辑
break;
case 值3:
// 符合结果的业务逻辑
break;
default:
// 都不符合的情况
}
示例:
public static void main(String[] args) {
char level = 'B';
switch (level) {
case 'A':
System.out.println("优秀");
break;
case 'B':
System.out.println("良好");
break;
case 'C':
System.out.println("一般");
break;
default:
System.out.println("差");
}
}
示例输出:
良好
- break 值得注意的是,case 中的
break;
关键字非常的重要,作用是终止后续的判断,并结束整个代码块;如果没有break,代码会继续执行下一个case,直到遇到break或者switch代码块结束,如下示例:java当我们注释调上面示例中的两个break,public static void main(String[] args) { char level = 'B'; switch (level) { case 'A': System.out.println("优秀"); // break; case 'B': System.out.println("良好"); // break; case 'C': System.out.println("一般"); break; default: System.out.println("差"); } }
case 'A'
没有匹配上,跳过;case 'B'
由于没有break,代码会继续执行case 'C'
,所以导致最终的输出为:良好
一般
Java 14 switch 新语法
简单示例
以下语法只能在JDK 14 及之后的版本才会生效,之前的版本会报语法错误;
javachar level = 'B'; switch (level) { case 'A' -> System.out.println("优秀"); case 'B' -> System.out.println("良好"); case 'C','D' -> System.out.println("一般"); default -> System.out.println("差"); };
输出:
良好
使用新的语法,就不需要break,不会出现穿透现象,而且case 后面允许跟多个值,使用
,
隔开;返回值及
yield
关键字新的语法不仅更加的简洁,而且还能返回简单的值;
如下示例,根据登录,返回评分:
javapublic static void main(String[] args) { char level = 'E'; int score = switch (level) { case 'A' -> 100; case 'B' -> 80; case 'C', 'D' -> { System.out.println("要努力啦!"); yield 60; } default -> { System.out.println("请家长!"); yield foo(); } }; System.out.println(score); } public static int foo() { return 40; }
- 返回值类型必须统一,否则会报错
- 当如果只需要返回评分值,就之间将值跟在
->
语法后面,如上示例的100、80; - 如果有更多的代码需要执行,可以添加代码块,然后使用yield关键字返回,如60;
- yield不仅可以直接返回一个值,还能调用一个方法,如上示例的
foo()
示例输出:
请家长
40
循环控制
循环语句是在特定的条件之下,重复执行某一段代码块;
循环由四部分组成
初始部分:循环判断的变量
循环条件:
布尔表达式,条件非常的重要,如果表达式有误可能导致循环不进入循环体或者成为死循环;
循环操作:循环执行的代码
迭代部分:更新循环变量
Java 中主要的循环方式
- while 循环
- do...while 循环
- for 循环
- 数组增强型 for 循环
循环方式
while 循环
语法结构
java[初始部分] while( 循环条件 ) { [循环操作] [迭代部分] // 更新初始值等 }
执行过程:
- 首先初始化初始值
- 执行【循环条件】部分的表达式,如果返回值为true,执行循体体
- 执行【迭代部分】代码,更新循环变量,再次判断循环条件,直到循环条件为false,跳出循环
示例
java// 循环判断出5的倍数 public static void whileTest() { int i = 1; // 【初始部分】 while (i <= 10) { // 【循环条件】 { // 【循环体】 这个{}可以没有,这里为了方便看那部分为代码块 if (i % 5 == 0) { System.out.println(i + "是5的倍数"); } else { System.out.println(i + "不是5的倍数"); } } i++; // 【迭代部分】 循环一次i+1 } }
示例输出:
java1不是5的倍数 2不是5的倍数 3不是5的倍数 4不是5的倍数 5是5的倍数 6不是5的倍数 7不是5的倍数 8不是5的倍数 9不是5的倍数 10是5的倍数
do...while 循环
相比与for、while,do...while情况特殊一点点,【循环条件】是后判断,也就意味着不管条件是否满足,【循环体】最少会执行一次;
语法结构
java[初始部分] do { [循环操作] [迭代部分] // 更新初始值等 }while( 循环条件 );
执行过程:
- 初始化初始值
- 执行循环体
- 判断循环条件,为 true 是继续执行循环体,false 结束循环
- 执行【迭代部分】代码,更新循环变量,再次判断循环条件,直到循环条件为false,跳出循环
示例
java// 计算1-100的累加 public static void doWhileTest() { int i = 1, sum = 0; // 【初始部分】 do { sum += i; // 【循环体】 i++; //【迭代部分】 循环一次i+1 } while (i <= 100); // 【循环条件】 System.out.println("1-100的累加:" + sum); }
示例输出:
1-100的累加:5050
for 循环
语法
javafor ( 初始部分 ; 循环条件 ; 迭代部分 ) { 【循环体】 }
执行顺序
- 初始化初始值
- 判断循环条件,为 true 执行循环体,为 false 结束循环
- 执行循环体
- 执行【迭代部分】代码,更新循环变量,再次判断循环条件,直到循环条件为false,跳出循环
示例
java// 计算1-100的累加 public static void forTest() { int sum = 0; // 【初始部分】 累加的变量 // int i = 1; 【初始部分】 // i <= 100; 【循环条件】 // i++ 【迭代部分】 循环一次i+1 for (int i = 1; i <= 100; i++) { sum += i; // 【循环体】 } System.out.println("1-100的累加:" + sum); }
示例输出:
1-100的累加:5050
数组增强型 for 循环
主要用于快速遍历数组或者一个实现了Interable接口类的对象,比如:ArrayList
- 语法java
for( 元素类型 变量名: 数组 ){ // 处理当前元素的逻辑 }
- 示例java示例输出:
// 计算数组元素的累加 public static void forArrayTest() { int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int sum = 0; // 【初始部分】 // 【循环条件】 数组的长度 // 【迭代部分】 下一个元素 for (int item : arr) { sum += item; // 【循环体】 } System.out.println("数组元素的累加:" + sum); }
数组元素的累加:55
三种循环的差异
语法差异
三种循环方式有着不同的语法,详情可见
执行顺序
- while 和 for 会优先执行循环条件,返回true才会进入循环体,可能一次都不会执行;
- do...while 是先执行循环体,在执行循环条件,所以do...while循环至少会执行一次;
场景建议
- 循环次数确定,建议使用 while 和 for 循环;
- 循环次数不确定,建议使用do...while;
循环终止、跳过
【循环体】的执行过程除了能通过【循环条件】控制之外,还可以在【循环体】中通过关键词break
,continue
控制循环;
break
在【循环体】中执行 break 会直接结束整个循环
示例:
在没有循环条件下累加1-100,当累加数大于100时,通过break终止
java// 在没有循环条件下累加1-100,当累加数大于100时,通过break终止 public static void doWhileBreakTest() { int i = 0, sum = 0; // 【初始部分】 do { i++; //【迭代部分】 循环一次i+1 if (i > 100) { // 通过循环体中break结束循环 break; } sum += i; // 【循环体】 } while (true); // 没有循环条件 System.out.println("1-100的累加:" + sum); }
示例输出:
1-100的累加:5050
continue
在【循环体】中执行 continue 会跳过本次循环,进入下一次循环,本次循环 continue 之后的代码将不再继续执行;
值得注意的是,for循环的循环体执行continue之后,会自动执行【迭代部分】代码;而 while 和 do...while 【迭代部分】代码也是循环体中的一部分,因此需要自行控制好【迭代部分】代码的执行,避免出现死循环;
示例:
计算1-100 偶数的累加
java// 计算1-100 偶数的累加 public static void forContinueTest() { int sum = 0; // 【初始部分】 // int i = 1; 【初始部分】 // i <= 100; 【循环条件】 // i++ 【迭代部分】 循环一次i+1 for (int i = 1; i <= 100; i++) { // 奇数跳过 if (i % 2 != 0) { continue; } sum += i; // 【循环体】 } System.out.println("1-100偶数的累加:" + sum); }
示例输出:
1-100偶数的累加:2550
嵌套循环
前面介绍了不同的循环形式,循环不仅可以单独使用,也可以嵌套使用(循环里面嵌套循环)
形式:
for ( 初始部分 ; 循环条件 ; 迭代部分 ) {
for ( 初始部分 ; 循环条件 ; 迭代部分 ) {
// 循环体
}
}
// 如:
for(int i = 0; i < 10 ; i++){
for(int j = 0; j < 20 ; j++){
// 业务操作
}
}
说明:
- 外层执行一次,内部循环会执行一遍,如上示例,业务操作会执行10 * 20 = 200 次
- 注意变量的作用域,内层循环可以使用外层的变量,外层不能使用内存的变量;如上示例,内存循环可以使用变量i,外层不能使用变量j
- 嵌套层数不要太多,最好不要超过三层,提高代码的可读性
示例:通过嵌套循环,打印九九乘法表
输出形式一
javafor (int i = 1; i <= 9; i++) { for (int j = 1; j <= i; j++) { System.out.printf("%d * %d = %d\t", i, j, i * j); } // 换行 System.out.println(); }
输出:
java1 * 1 = 1 2 * 1 = 2 2 * 2 = 4 3 * 1 = 3 3 * 2 = 6 3 * 3 = 9 4 * 1 = 4 4 * 2 = 8 4 * 3 = 12 4 * 4 = 16 5 * 1 = 5 5 * 2 = 10 5 * 3 = 15 5 * 4 = 20 5 * 5 = 25 6 * 1 = 6 6 * 2 = 12 6 * 3 = 18 6 * 4 = 24 6 * 5 = 30 6 * 6 = 36 7 * 1 = 7 7 * 2 = 14 7 * 3 = 21 7 * 4 = 28 7 * 5 = 35 7 * 6 = 42 7 * 7 = 49 8 * 1 = 8 8 * 2 = 16 8 * 3 = 24 8 * 4 = 32 8 * 5 = 40 8 * 6 = 48 8 * 7 = 56 8 * 8 = 64 9 * 1 = 9 9 * 2 = 18 9 * 3 = 27 9 * 4 = 36 9 * 5 = 45 9 * 6 = 54 9 * 7 = 63 9 * 8 = 72 9 * 9 = 81
\t 表示退格
输出形式二
javafor (int i = 1; i <= 9; i++) { for (int j = 1; j <= i; j++) { System.out.printf("%d * %d = %d\t", j, i, i * j); } // 换行 System.out.println(); }
输出:
java1 * 1 = 1 1 * 2 = 2 2 * 2 = 4 1 * 3 = 3 2 * 3 = 6 3 * 3 = 9 1 * 4 = 4 2 * 4 = 8 3 * 4 = 12 4 * 4 = 16 1 * 5 = 5 2 * 5 = 10 3 * 5 = 15 4 * 5 = 20 5 * 5 = 25 1 * 6 = 6 2 * 6 = 12 3 * 6 = 18 4 * 6 = 24 5 * 6 = 30 6 * 6 = 36 1 * 7 = 7 2 * 7 = 14 3 * 7 = 21 4 * 7 = 28 5 * 7 = 35 6 * 7 = 42 7 * 7 = 49 1 * 8 = 8 2 * 8 = 16 3 * 8 = 24 4 * 8 = 32 5 * 8 = 40 6 * 8 = 48 7 * 8 = 56 8 * 8 = 64 1 * 9 = 9 2 * 9 = 18 3 * 9 = 27 4 * 9 = 36 5 * 9 = 45 6 * 9 = 54 7 * 9 = 63 8 * 9 = 72 9 * 9 = 81
死循环
死循环在业务开发时,几乎不会用到,如果在特定的场景下,希望代码一直运行,不终止,就会用到死循环,三种循环方式的死循环稍微有点差异:
- while 死循环java
while( true ){ // 没有循环条件 // 循环体 }
- do...while 死循环java
do{ // 循环体 }while( true ); // 没有循环条件
- for 死循环java
for(;;){ // 没有循环条件 // 循环体 }