分支

分支控制有三种: 单分支, 双分支, 多分支.

单分支

基本语法:

if (条件表达式) {
    执行代码块;
}

程序示例:

import java.util.Scanner;

public class If01 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("输入你的年龄:");
        int age = sc.nextInt();
        if (age > 18) {
            System.out.println("你的年龄大于18. ");
        }
    }
}

正常情况下, if 后面的语句如果只有一句话, 那么花括号是可以省略的, 但是下面的语句会报错:

public class Test {
    public static void main(String[] args) {
        int a = 10;
        if (a > 10)
            int b = 20;  // 报错: Declaration not allowed here
    }
}

原因是, int b = 20; 其实是做了两件事: 1. 声明变量 b. 2. 给变量 b 赋值 20.

int b = 20; 是一个语法糖.

双分支

基本语法:

if (条件表达式) {
    执行代码块1;
} else {
    执行代码块2;
}

程序示例:

import java.util.Scanner;

public class If02 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("输入你的年龄:");
        int age = sc.nextInt();
        if (age > 18) {
            System.out.println("你已经超过18岁了. ");
        } else {
            System.out.println("你还未成年. ");
        }
    }
}

多分支

基本语法:

if (条件表达式1) {
    执行代码块1;
} 
else if (条件表达式2) {
    执行代码块2;
}
......
else {
    执行代码块n;
}

多分支最后可以没有 else.

如果没有 else, 当前面的所有 if 都不成立时, 将什么都不执行.

switch

switch(表达式) 中的表达式数据类型要么和 case 常量中常量的类型一致, 要么是可以自动类型转换为可以进行比较的类型.

case 标签的值自动类型转化为 switch 表达式的类型:

public class Test {
    public static void main(String[] args) {
        int a = 97;
        switch (a) {
            case 'a':
                System.out.println("字符 a");
                break;
            case 'b':
                System.out.println("字符 b");
                break;
        }
    }
}

执行结果:

字符 a

switch 表达式的类型自动类型转化为 case 标签的值的类型:

public class Test {
    public static void main(String[] args) {
        char a = 'a';
        switch (a) {
            case 97:
                System.out.println("字符 a");
                break;
            case 98:
                System.out.println("字符 b");
                break;
        }
    }
}

执行结果:

字符 a

switch(表达式) 中的表达式的值的类型必须是以下类型中的一种: byte, short, char, int, enum (JKD 5 之后支持), String (JDK 7 之后支持).

case 常量中的常量可以是常量表达式, 即值为常量的表达式, 如 'b' + 1. case 标签还可以是字符串或枚举类型常量.

default 可以省略.

default 的位置随意.

多个 case 中的值不允许重复.

case 后面如果没有 break 将会穿透. 如果多个 case 的语句体相同, 则可以利用穿透来简化代码.

程序示例:

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        // 从键盘输入学生成绩, 如果学生成绩大于 60 则输出合格, 否则输出不合格
        // 要求用 switch 完成
        System.out.println("输入学生成绩:");
        Scanner sc = new Scanner(System.in);
        int score = sc.nextInt();
        switch (score / 60) {
            case 0:
                System.out.println("不合格");
                break;
            case 1:
                System.out.println("合格");
                break;
        }
    }
}

程序示例:

public class Test {
  public static void main(String[] args) {
    int a = 10;
    switch (a) {
      case 10: {
        System.out.println("hello");
      }
      case 20: {
        System.out.println("OK");
      }
      default:
        break;
    }
  }
}

执行结果:

hello
OK

上面代码说明, 按照传统的写法, 即便 case 后面的代码用花括号括起来了, 如果没有 break, 也会发生穿透.

程序示例:

public class Test {
    public static void main(String[] args) {
        char a = 'a';
        switch (a) {
            case 97:
                System.out.println("字符 a");
                System.out.println("字符 a, 一个 case 有多条语句, 看看如何打印");
                break;
            case 98:
                System.out.println("字符 b");
                System.out.println("字符 b, 一个 case 有多条语句, 看看如何打印");
                break;
        }
    }
}

执行结果:

字符 a
字符 a, 一个 case 有多条语句, 看看如何打印

说明 case 后面如果有多条语句, 是不需要花括号的.

程序示例:

// 这是从 JDK 12 开始引入的新特性, case 后面跟箭头则可以省略 break, 因为不会发生穿透现象
public class Test {
    public static void main(String[] args) {
        int number = 1;
        switch (number) {
            case 1 -> {
                System.out.println("一");
                break;
            }
            case 2 -> {
                System.out.println("二");
                break;
            }
            case 3 -> {
                System.out.println("三");
                break;
            }
            default -> {
                System.out.println("没有这种选项");
                break;
            }
        }
    }
}

省略 break:

public class Test {
    public static void main(String[] args) {
        int number = 1;
        switch (number) {
            case 1 -> {
                System.out.println("一");
            }
            case 2 -> {
                System.out.println("二");
            }
            case 3 -> {
                System.out.println("三");
            }
            default -> {
                System.out.println("没有这种选项");
            }
        }
    }
}

用花括号括起来的语句块只有一条语句时, 可以省略花括号:

// 用花括号括起来的语句块只有一条语句时, 可以省略花括号
public class Test {
    public static void main(String[] args) {
        int number = 1;
        switch (number) {
            case 1 -> System.out.println("一");
            case 2 -> System.out.println("二");
            case 3 -> System.out.println("三");
            default -> System.out.println("没有这种选项");
        }
    }
}

总结: case 后面如果是冒号, 则可能发生穿透, 如果不需要穿透, 则在 case 后面加 break, 如果需要穿透, 则 case 后面不要加 break. 如果 case 后面是箭头, 则不可能发生穿透. 是否发生穿透和 case 后面的语句是否有花括号无关.

冒号和箭头两种格式不能混着用.

程序示例:

public class Test {
    public static void main(String[] args) {
        int a = 10;
        switch (a) {
            case 10:
                System.out.println("值为 10");
            case 20:
                System.out.println("值为 20");
            default:
                System.out.println("值不存在");  // case 穿透可以一直穿透到 default 中
        }
    }
}

执行结果:

值为 10
值为 20
值不存在

程序示例:

public class Test {
    public static void main(String[] args) {
        int a = 40;
        switch (a) {
            default:
                System.out.println("值不存在");  // case 穿透可以从 default 中开始
            case 10:
                System.out.println("值为 10");
            case 20:
                System.out.println("值为 20");
        }
    }
}

执行结果:

值不存在
值为 10
值为 20

如果 case 后面是箭头且不止一条语句, 则必须用花括号括起来, 程序示例:

public class Test {
    public static void main(String[] args) {
        int a = 40;
        switch (a) {
            case 10 -> System.out.println("值为 10");
            System.out.println("还有一句话");  // 报错: Statement must be prepended with case label
            case 20 -> System.out.println("值为 20");
            default:
                System.out.println("值不存在");
        }
    }
}

如果多个 case 的语句体相同, 则可以利用穿透来简化代码. 未简化的代码:

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入星期数:");
        int number = sc.nextInt();
        switch (number) {
            case 1:
                System.out.println("工作日");
                break;
            case 2:
                System.out.println("工作日");
                break;
            case 3:
                System.out.println("工作日");
                break;
            case 4:
                System.out.println("工作日");
                break;
            case 5:
                System.out.println("工作日");
                break;
            case 6:
                System.out.println("休息日");
                break;
            case 7:
                System.out.println("休息日");
                break;
            default:
                System.out.println("输入错误");
                break;
        }
    }
}

利用 case 穿透进行简化:

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入星期数:");
        int number = sc.nextInt();
        switch (number) {
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                System.out.println("工作日");
                break;
            case 6:
            case 7:
                System.out.println("休息日");
                break;
            default:
                System.out.println("输入错误");
                break;
        }
    }
}

进一步简化:

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入星期数:");
        int number = sc.nextInt();
        switch (number) {
            case 1, 2, 3, 4, 5:                  // 可以为一个 case 提供多个标签, 各个标签之间用逗号分隔
                System.out.println("工作日");
                break;
            case 6, 7:
                System.out.println("休息日");
                break;
            default:
                System.out.println("输入错误");
                break;
        }
    }
}

更进一步简化:

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入星期数:");
        int number = sc.nextInt();
        switch (number) {
            case 1, 2, 3, 4, 5 -> System.out.println("工作日");  // 可以为一个 case 提供多个标签, 各个标签之间用逗号分隔
            case 6, 7 -> System.out.println("休息日");
            default -> System.out.println("输入错误");
        }
    }
}

与所有表达式类似, switch 表达式也有一个值, 可以将 switch 的结果赋值给一个变量.

程序示例:

import java.util.Scanner;

public class SwitchDemo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入一个季节:");
        String season = sc.next();
        int numLetters = switch (season) {
            case "spring", "summer", "winter" -> 6;
            case "fall" -> 4;
            default -> -1;
        };
        System.out.println(numLetters);
    }
}

执行结果:

请输入一个季节:fall
4

switch 表达式中使用枚举常量时, 不需要为各个标签提供枚举名, 这可以从 switch 值推导得出.

程序示例:

public class Test {
    public static void main(String[] args) {
        enum Size {SMALL, MEDIUM, LARGE, EXTRA_LARGE}
        
        Size itemSize = Size.SMALL;
        String label = switch (itemSize) {
            case SMALL -> "S"; // no need to use Size.SMALL
            case MEDIUM -> "M";
            case LARGE -> "L";
            case EXTRA_LARGE -> "XL";
        }; // 在这个例子中, 完全可以省略 default, 因为每一个可能的值都有相应的一个 case
        System.out.println(label);  // S
    }
}

使用整数或 String 操作数的 switch 表达式必须有一个 default, 因为不论操作数值是什么, 这个表达式都必须生成一个值.

如果操作数为 null, 会抛出一个 NullPointerException.

posted @ 2024-08-31 18:48  有空  阅读(50)  评论(0)    收藏  举报