Skip to content
目录概览

流程控制

分支控制

在Java语言中,提供了两种常见的分支控制结构:

  • if 条件语句
  • switch 语句

if 条件语句

if 语句使用布尔值或者布尔值表达式来做流程控制,主要表现为两种形式:

  • 仅有 if 判断

    java
    if( 布尔返回值的条件 ) {
      // 条件符合的业务逻辑
    }

    // 如下示例,if判断就不会执行

    java
    int age = 10;
    if(age > 18) {
      System.out.println("成年人");
    }
  • if else 判断

    java
    if( 布尔返回值的条件 ) {
      // 条件符合的业务逻辑
    }else{
      // 条件不符的业务逻辑
    }

    // 如下示例,控制台会输出“未成年”

    java
    int age = 10;
    if(age > 18) {
      System.out.println("成年人"); // 由于条件不符合,这段代码不会执行
    }else {
      System.out.println("未成年"); // 会执行这段代码
    }
  • 多 if 条件判断

    多 if 条件时,会从上往下逐个判断,只要其中一个满足条件,就不会再执行其他判断,包括else;

    java
    if( 布尔返回值的条件1 ){
      // 条件1符合的业务逻辑
    }else if( 布尔返回值的条件2 ){
      // 条件2符合的业务逻辑        
    }else{
      // 条件都不符的业务逻辑
    }
    java
    int 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 之后)
java
switch( 表达式 ){
  case 值1:
    // 符合结果的业务逻辑
    break;
  case 值2:
    // 符合结果的业务逻辑
    break;
  case 值3:
    // 符合结果的业务逻辑
    break;
  default:
    // 都不符合的情况
}

示例:

java
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
    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 'A'没有匹配上,跳过;case 'B'由于没有break,代码会继续执行case 'C',所以导致最终的输出为:

    良好

    一般

Java 14 switch 新语法

  • 简单示例

    以下语法只能在JDK 14 及之后的版本才会生效,之前的版本会报语法错误;

    java
    char 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关键字

    新的语法不仅更加的简洁,而且还能返回简单的值;

    如下示例,根据登录,返回评分:

    java
    public 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
        }
    }

    示例输出:

    java
    1不是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 循环

  • 语法

    java
    for ( 初始部分 ; 循环条件 ; 迭代部分 ) {
        【循环体】
    }

    执行顺序

    • 初始化初始值
    • 判断循环条件,为 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

嵌套循环

前面介绍了不同的循环形式,循环不仅可以单独使用,也可以嵌套使用(循环里面嵌套循环)

形式:

java
for ( 初始部分 ; 循环条件 ; 迭代部分 ) {
    for ( 初始部分 ; 循环条件 ; 迭代部分 ) {
        // 循环体
    }
}

// 如:
for(int i = 0; i < 10 ; i++){
    for(int j = 0; j < 20 ; j++){
       // 业务操作
    }
}

说明:

  • 外层执行一次,内部循环会执行一遍,如上示例,业务操作会执行10 * 20 = 200 次
  • 注意变量的作用域,内层循环可以使用外层的变量,外层不能使用内存的变量;如上示例,内存循环可以使用变量i,外层不能使用变量j
  • 嵌套层数不要太多,最好不要超过三层,提高代码的可读性

示例:通过嵌套循环,打印九九乘法表

  • 输出形式一

    java
    for (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();
    }

    输出:

    java
    1 * 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 表示退格

    点击查看System.out.printf用法

  • 输出形式二

    java
    for (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();
    }

    输出:

    java
    1 * 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(;;){ // 没有循环条件
      // 循环体
    }