第13章

Java switch语句

掌握多分支选择语句的语法结构和使用技巧

学习目标

switch语句基础

switch语句是Java中的多分支选择语句,它允许程序根据一个表达式的值来选择执行不同的代码块。相比于多个if-else语句,switch语句在处理多个固定值的判断时更加简洁和高效。

基本语法

语法结构:
switch (表达式) {
    case 值1:
        // 代码块1
        break;
    case 值2:
        // 代码块2
        break;
    default:
        // 默认代码块
        break;
}
  • 表达式的值与case标签匹配
  • 执行匹配的case代码块
  • break语句跳出switch
  • default处理未匹配情况

执行流程

执行示例:
int day = 3;
switch (day) {
    case 1:
        System.out.println("星期一");
        break;
    case 2:
        System.out.println("星期二");
        break;
    case 3:
        System.out.println("星期三"); // 执行这里
        break;
    default:
        System.out.println("其他");
}
  • 计算switch表达式的值
  • 从上到下匹配case标签
  • 执行匹配的代码块
  • 遇到break或结束时退出

支持的数据类型

switch语句支持多种数据类型,随着Java版本的发展,支持的类型也在不断增加。

数据类型 Java版本 示例 说明
byte, short, int Java 1.0+ int num = 1; 基本整数类型
char Java 1.0+ char ch = 'A'; 字符类型
enum Java 5+ Day.MONDAY 枚举类型
String Java 7+ "hello" 字符串类型
包装类 Java 5+ Integer, Character 自动拆箱支持
不同数据类型示例:
// 整数类型
int score = 85;
switch (score / 10) {
    case 10:
    case 9:
        System.out.println("优秀");
        break;
    case 8:
        System.out.println("良好");
        break;
    default:
        System.out.println("需要努力");
}

// 字符类型
char grade = 'A';
switch (grade) {
    case 'A':
        System.out.println("优秀");
        break;
    case 'B':
        System.out.println("良好");
        break;
    case 'C':
        System.out.println("及格");
        break;
    default:
        System.out.println("不及格");
}

// 字符串类型(Java 7+)
String season = "春天";
switch (season) {
    case "春天":
        System.out.println("万物复苏");
        break;
    case "夏天":
        System.out.println("烈日炎炎");
        break;
    case "秋天":
        System.out.println("硕果累累");
        break;
    case "冬天":
        System.out.println("雪花飞舞");
        break;
    default:
        System.out.println("未知季节");
}

break语句和fall-through

break语句在switch中起到跳出的作用。如果省略break,程序会继续执行下一个case,这种现象称为"fall-through"。

注意:忘记写break语句是switch语句中最常见的错误之一,会导致意外的程序行为。
break语句的重要性:
// 错误示例:缺少break语句
int month = 3;
switch (month) {
    case 3:
        System.out.println("三月");  // 会执行
    case 4:
        System.out.println("四月");  // 也会执行!
    case 5:
        System.out.println("五月");  // 还会执行!
        break;
    default:
        System.out.println("其他月份");
}
// 输出:三月 四月 五月

// 正确示例:使用break语句
switch (month) {
    case 3:
        System.out.println("三月");
        break;  // 跳出switch
    case 4:
        System.out.println("四月");
        break;
    case 5:
        System.out.println("五月");
        break;
    default:
        System.out.println("其他月份");
}
// 输出:三月
巧用fall-through:有时候我们可以故意省略break来实现多个case执行相同的代码。
合理使用fall-through:
// 工作日和周末的判断
int dayOfWeek = 6;
switch (dayOfWeek) {
    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("无效的星期");
}

// 季节判断
int month = 4;
switch (month) {
    case 3:
    case 4:
    case 5:
        System.out.println("春季");
        break;
    case 6:
    case 7:
    case 8:
        System.out.println("夏季");
        break;
    case 9:
    case 10:
    case 11:
        System.out.println("秋季");
        break;
    case 12:
    case 1:
    case 2:
        System.out.println("冬季");
        break;
    default:
        System.out.println("无效的月份");
}

switch表达式(Java 14+)

Java 14引入了switch表达式,它是switch语句的增强版本,可以返回值,语法更加简洁,并且避免了fall-through的问题。

传统switch语句 vs switch表达式:
// 传统switch语句
int dayOfWeek = 3;
String dayType;
switch (dayOfWeek) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        dayType = "工作日";
        break;
    case 6:
    case 7:
        dayType = "周末";
        break;
    default:
        dayType = "无效";
}

// switch表达式(Java 14+)
String dayType = switch (dayOfWeek) {
    case 1, 2, 3, 4, 5 -> "工作日";
    case 6, 7 -> "周末";
    default -> "无效";
};

// 复杂逻辑的switch表达式
String result = switch (dayOfWeek) {
    case 1 -> {
        System.out.println("新的一周开始");
        yield "星期一";
    }
    case 2, 3, 4 -> "工作日";
    case 5 -> {
        System.out.println("快到周末了");
        yield "星期五";
    }
    case 6, 7 -> "周末";
    default -> throw new IllegalArgumentException("无效的星期: " + dayOfWeek);
};
switch表达式的优势:
  • 可以返回值,减少临时变量
  • 使用箭头语法,避免fall-through
  • 支持多个case值用逗号分隔
  • 使用yield关键字返回复杂表达式的值

实际应用示例

💻 查看完整代码 - 在线IDE体验
计算器示例:
public class Calculator {
    public static double calculate(double a, double b, char operator) {
        return switch (operator) {
            case '+' -> a + b;
            case '-' -> a - b;
            case '*' -> a * b;
            case '/' -> {
                if (b == 0) {
                    throw new ArithmeticException("除数不能为零");
                }
                yield a / b;
            }
            case '%' -> a % b;
            default -> throw new IllegalArgumentException("不支持的运算符: " + operator);
        };
    }
    
    public static void main(String[] args) {
        System.out.println(calculate(10, 5, '+'));  // 15.0
        System.out.println(calculate(10, 5, '-'));  // 5.0
        System.out.println(calculate(10, 5, '*'));  // 50.0
        System.out.println(calculate(10, 5, '/'));  // 2.0
    }
}
成绩等级判断:
public class GradeEvaluator {
    public static String getGrade(int score) {
        // 输入验证
        if (score < 0 || score > 100) {
            return "无效分数";
        }
        
        return switch (score / 10) {
            case 10, 9 -> "A (优秀)";
            case 8 -> "B (良好)";
            case 7 -> "C (中等)";
            case 6 -> "D (及格)";
            default -> "F (不及格)";
        };
    }
    
    public static String getDetailedGrade(int score) {
        return switch (score / 10) {
            case 10 -> {
                if (score == 100) {
                    yield "A+ (满分)";
                } else {
                    yield "A (优秀)";
                }
            }
            case 9 -> "A (优秀)";
            case 8 -> "B (良好)";
            case 7 -> "C (中等)";
            case 6 -> "D (及格)";
            default -> "F (不及格)";
        };
    }
}

最佳实践

switch语句使用建议

推荐做法

  • 总是使用break:除非故意使用fall-through
  • 包含default分支:处理未预期的值
  • 保持case简洁:复杂逻辑提取到方法中
  • 使用常量:避免魔法数字
  • 考虑枚举:相关常量组合使用枚举
  • 优先使用switch表达式:Java 14+项目中

避免做法

  • 忘记break语句:导致意外的fall-through
  • 省略default分支:可能遗漏边界情况
  • case中写复杂逻辑:影响代码可读性
  • 使用浮点数:switch不支持float/double
  • case标签重复:编译错误
  • 在case中声明变量:作用域问题
最佳实践示例:
// 使用枚举和switch表达式
public enum Priority {
    LOW, MEDIUM, HIGH, URGENT
}

public class TaskManager {
    public static String getTaskDescription(Priority priority) {
        return switch (priority) {
            case LOW -> "可以稍后处理";
            case MEDIUM -> "正常优先级任务";
            case HIGH -> "需要尽快处理";
            case URGENT -> "紧急任务,立即处理";
        };
    }
    
    public static int getProcessingTime(Priority priority) {
        return switch (priority) {
            case LOW -> 24;      // 24小时内
            case MEDIUM -> 8;    // 8小时内
            case HIGH -> 2;      // 2小时内
            case URGENT -> 1;    // 1小时内
        };
    }
}

常见错误和陷阱

常见错误总结:
  1. 忘记break语句 - 导致fall-through
  2. case标签重复 - 编译错误
  3. 在case中声明变量 - 作用域混乱
  4. 使用不支持的数据类型 - 如float、double
  5. null值处理 - 可能导致NullPointerException
错误示例和修正:
// 错误:在case中声明变量
switch (type) {
    case 1:
        int value = 10;  // 错误:变量声明
        break;
    case 2:
        int value = 20;  // 错误:重复声明
        break;
}

// 正确:使用代码块
switch (type) {
    case 1: {
        int value = 10;  // 正确:在代码块中声明
        System.out.println(value);
        break;
    }
    case 2: {
        int value = 20;  // 正确:不同作用域
        System.out.println(value);
        break;
    }
}

// 错误:null值处理
String str = null;
switch (str) {  // 运行时抛出NullPointerException
    case "hello":
        System.out.println("Hello");
        break;
}

// 正确:null值检查
if (str != null) {
    switch (str) {
        case "hello":
            System.out.println("Hello");
            break;
        default:
            System.out.println("Other");
    }
} else {
    System.out.println("String is null");
}

章节总结