
第5章 条件控制if / switch程序不是永远从上到下顺序执行的。本节学习让程序做判断的两种语句if 语句和 switch 语句。判断是程序三大结构顺序、分支、循环里的分支。一、if 语句的三种形式1. 单分支 ifintscore85;if(score60){System.out.println(及格了);}条件为 true 才执行大括号内的代码。适合要不要做的场景满足条件就做不满足就跳过没有第二种选择。2. if-else 双分支intscore45;if(score60){System.out.println(及格了);}else{System.out.println(不及格继续努力);}二选一必走其一。适合做 A 还是做 B的场景// 实战根据天气决定带不带伞booleanisRainingtrue;if(isRaining){System.out.println(带伞出门);}else{System.out.println(不用带伞);}3. if-else if-else 多分支intscore92;if(score90){System.out.println(优秀);}elseif(score80){System.out.println(良好);}elseif(score60){System.out.println(及格);}else{System.out.println(不及格);}从上往下逐个判断一旦某个条件成立后面的分支不再判断。注意条件的书写顺序范围判断要从小到大或从大到小排列比如上面的score 90必须写在score 80前面否则 92 分会被当成良好具体对照见易错点。二、if 的常见坑1. 大括号建议不要省略if(score60)System.out.println(及格);System.out.println(这是另一条语句);// 注意这行不在 if 里Java 允许 if 后面只跟一条语句但这样极易写错。始终加花括号是良好习惯。2. 判断相等要用而不是if(score60){// 编译报错int 不能转 boolean是赋值才是比较写错会导致编译错误或逻辑错误。3. 浮点数不要直接比较相等doublea0.10.2;// 实际是 0.30000000000000004if(a0.3){// false浮点数有精度误差判断相等应该用差值小于一个极小值if(Math.abs(a-0.3)0.000001){System.out.println(近似相等);}三、switch 语句switch 适合对某个变量做固定值判断的场景比 if-else if 更清晰intday3;switch(day){case1:System.out.println(星期一);break;case2:System.out.println(星期二);break;case3:System.out.println(星期三);break;default:System.out.println(未知的日期);break;}执行流程拿day的值和每个case比较匹配成功从该 case 开始往下执行遇到break才跳出 switch没有 break 会发生穿透继续执行后面的 case穿透示例intmonth7;switch(month){case1:case3:case5:case7:case8:case10:case12:System.out.println(31 天);break;case4:case6:case9:case11:System.out.println(30 天);break;default:System.out.println(2 月28 或 29 天);}利用穿透特性多个值共用一段逻辑代码非常简洁。支持的类型switch 可以判断byte、short、int、char、String、枚举。这几种类型在本系列讲解的 JDK 8/11/17 里都支持String 和枚举也不例外。Stringfruitapple;switch(fruit){caseapple:System.out.println(苹果);break;casebanana:System.out.println(香蕉);break;default:System.out.println(不认识的水果);}default 的位置与 case 的约束default表示所有 case 都没匹配上时的兜底写在哪个位置都合法但约定俗成放最后可读性最好。另外case 后面只能跟字面量或常量不能是变量因为 switch 在编译期就要生成跳转表报错示例见易错点。JDK 17 的 switch 新写法箭头表达式如果你用的是 JDK 17switch 还有一种更简洁的写法用-代替case ... break自动 break不会穿透switch(day){case1-System.out.println(星期一);case2-System.out.println(星期二);default-System.out.println(其他);}甚至可以把 switch 当表达式用直接返回一个值这个写法需要 JDK 17 才能运行Stringnameswitch(day){case1-星期一;case2-星期二;default-其他;};如果你还在用 JDK 8 或 11switch 只能写前面的经典形式case break箭头写法是 JDK 17 才有的新特性老项目里见到的也大多是经典写法。四、if 还是 switch判断范围、大小关系分数、年龄→ 用 if判断固定值星期几、菜单选项→ 用 switch代码更直观分支很少2~3 个→ 用 if 更轻量JDK 17 且需要返回值 → switch 表达式需 JDK 17五、扩展知识1. 枚举与 switch枚举enum是一种取值被限定的类型比如方向、订单状态。用枚举做 switch 比用 String 更安全写错枚举常量编译直接报错写错字符串要等运行时才发现。// 场景订单状态流转enumOrderStatus{NEW,PAID,SHIPPED,DONE}OrderStatusstatusOrderStatus.PAID;switch(status){caseNEW:System.out.println(待支付);break;casePAID:System.out.println(已支付待发货);break;default:System.out.println(已发货或已完成);}// 输出已支付待发货枚举在 JDK 8/11/17 中都支持。注意case 里写枚举常量时不用带枚举名写case NEW即可不能写case OrderStatus.NEWJDK 17 的箭头写法同样适用需 JDK 17。2. JDK 17 switch 表达式返回值的实际用法JDK 17 中需 JDK 17 才能运行switch 表达式不仅能直接返回单行值还能在代码块里用yield返回多行计算的结果// 多行分支用 {} 包起来用 yield 返回结果需 JDK 17intday3;Stringtypeswitch(day){case1,2,3,4,5-工作日;case6,7-周末;default-{System.out.println(非法日期day);// 先做点副作用yield未知;// 再返回结果}};System.out.println(type);// 工作日// 实战switch 表达式的结果直接当方法返回值方法片段需放类中staticStringscoreLevel(intscore){returnswitch(score/10){case10,9-优秀;case8-良好;case7,6-及格;default-不及格;};}System.out.println(scoreLevel(95));// 优秀System.out.println(scoreLevel(72));// 及格注意箭头写法、yield、多标签case 1, 2, 3都是 JDK 17 新特性JDK 8/11 里没有需要 JDK 17 才能运行。六、综合练习判断某年是平年还是闰年能被 4 整除但不能被 100 整除或能被 400 整除intyear2024;if((year%40year%100!0)||year%4000){System.out.println(year 是闰年);}else{System.out.println(year 是平年);}再加一道用 switch 把 1~7 的数字转成中文星期三个版本通用intday25;Stringweek;switch(day2){case1:week星期一;break;case2:week星期二;break;case3:week星期三;break;case4:week星期四;break;case5:week星期五;break;case6:week星期六;break;case7:week星期日;break;default:week非法数字;}System.out.println(week);// 星期五七、易错点前面if 的常见坑讲过的内容这里用错误 / 正确对照复习并补充 switch 相关的坑。1. switch 忘了 break发生穿透// ❌ 忘了 break匹配到 case 1 后一路执行到底intday1;switch(day){case1:System.out.println(星期一);case2:System.out.println(星期二);}// 输出星期一 星期二穿透了// ✅ 每个 case 结束都写 breakswitch(day){case1:System.out.println(星期一);break;case2:System.out.println(星期二);break;}// 输出星期一2. 浮点数直接 比较// ❌ 精度误差导致永远不相等doublea0.10.2;if(a0.3){}// false// ✅ 用差值的绝对值小于极小值判断if(Math.abs(a-0.3)0.000001){System.out.println(近似相等);}3. else if 顺序写反范围判断错乱// ❌ 先判断宽范围窄范围分支永远走不到intscore92;if(score60){System.out.println(及格);}elseif(score90){System.out.println(优秀);// 死代码}// ✅ 范围判断从大到小或从小到大排列if(score90){System.out.println(优秀);}elseif(score60){System.out.println(及格);}4. if 后面省略大括号悬空 else// ❌ 省略大括号else 就近匹配最近的 ifinta1,b2;if(a0)if(b0)System.out.println(都大于 0);elseSystem.out.println(b 不大于 0);// else 属于内层 if// ✅ 始终加花括号逻辑一目了然if(a0){if(b0){System.out.println(都大于 0);}}else{System.out.println(a 不大于 0);}5. case 的值重复或不是常量// ❌ case 值重复编译报错// switch (x) { case 1: ... case 1: ... } // duplicate case label// ❌ case 后跟变量编译报错// int n 1; switch (x) { case n: ... } // 编译错误必须用常量表达式// ✅ case 后跟字面量/常量intx1;switch(x){case1:System.out.println(一);break;}6. case 里声明变量与作用域冲突// ❌ 两个 case 里声明同名变量case 之间共享作用域编译报错// switch (x) {// case 1: int v 10; break;// case 2: int v 20; break; // 编译错误v 重复定义// }// ✅ 用花括号圈起每个 case 的变量switch(1){case1:{intv10;System.out.println(v);break;}case2:{intv20;System.out.println(v);break;}}八、小结if 适合范围判断switch 适合固定值判断经典 switch 每个 case 别忘了 breakJDK 17 的-写法自动 break判断相等用浮点数比较要小心精度大括号始终加上避免悬空 else 问题枚举与 switch 是黄金搭档比 String 更安全JDK 17 的 switch 表达式可返回值多行逻辑用yield需 JDK 17 才能运行if 在 JDK 8/11/17 写法一致只有 switch 新写法需 JDK 17下一节学习循环语句。下一篇第6章 循环控制for / while / do-while