
Java流程控制之选择结构让程序学会做决定选择结构说白了就是让程序具备“做决定”的能力。一、程序的三大基本流程所有程序无论多复杂都由三种基本结构组合而成。结构类型执行方式顺序结构从上到下依次执行选择结构按条件选择执行路径循环结构重复执行某段代码二、if的三种形态由简到繁if是最常用的分支语句它由3种写法对应三种场景。2.1 单分支if满足就执行语法简介如果条件成立就做某事语法if(条件表达式){//条件为true时执行}intcas70;if(cas60){System.out.println(及格了继续加油)}//输出及格了继续加油执行流程先判断条件表达式的结果如果是true进大括号执行输出语句如果是false就跳过大括号中的内容。2.2 双分支if-else二选一语法“如果成立做A否则做B”——非此即彼的场景。if(条件表达式){// 条件为 true 时执行 A}else{// 条件为 false 时执行 B}经典例子判断奇偶数。intnum7;if(num%20){System.out.println(num是偶数);}else{System.out.println(num是奇数);}// 输出7是奇数要点if 和 else 两个分支有且只有一个会被执行绝不会都走也不会都不走。2.3 多分支 if-else if-else多条件选一当有 3 个及以上互斥条件时用 else if 串起来。if(条件1){// 满足条件1执行}elseif(条件2){// 满足条件2执行}elseif(条件3){// 满足条件3执行}else{// 以上都不满足时执行兜底}成绩评级是最经典的例子intscore85;if(score90){System.out.println(优秀);}elseif(score80){System.out.println(良好);// ← 命中这里}elseif(score60){System.out.println(及格);}else{System.out.println(不及格);}// 输出良好执行逻辑从上往下依次判断遇到第一个 true 就进对应分支执行完直接跳出整个 if后面的 else if 一律不再看。这叫短路式判断。⚠️多分支顺序很重要写多分支时条件之间必须互斥且有序。错误示范// ❌ 错误写法把 60 写在最前面if(score60){System.out.println(及格);// 85分会命中这里}elseif(score80){System.out.println(良好);// 永远走不到}85 明明应该是良好却被第一个条件截胡。写区间判断时记得范围小的、严格的放前面范围大的、宽松的放后面或者用明确的上下界比如score 80 score 90就不会出错。三、if 语句的 5 个高频坑坑1大括号省略带来的幽灵逻辑Java 语法规定if/else 后面如果只有一条语句可以省略大括号。但强烈不推荐// ❌ 看上去两句都属于 if其实只有第一句是if(score60)System.out.println(及格);System.out.println(恭喜你);// 这句永远都会执行第二行打印不受 if 控制无论及不及格都会输出。新手特别容易被缩进骗了——Java 不靠缩进控制代码块只看大括号。最佳实践哪怕只有一条语句也永远写上大括号{ }。能省掉 90% 的低级 Bug。坑2悬挂 else 问题看这段代码猜 else 属于哪个 ifinta5,b-1;if(a0)if(b0)System.out.println(都大于0);elseSystem.out.println(a 0);// 实际输出这个答案else 永远和最近的、未被匹配的 if配对。也就是内层的if (b 0)所以 a5、b-1 时输出a 0逻辑完全错了解决办法很简单老老实实写大括号。// ✅ 正确写法if(a0){if(b0){System.out.println(都大于0);}}else{System.out.println(a 0);}坑3赋值号与 比较号混用这是所有 C 系语言新手必踩的坑。booleanisViptrue;if(isVipfalse){// ❌ 这里是赋值不是比较System.out.println(VIP你好);}// 这段代码把 isVip 改成了 false条件永远不成立一个小技巧写比较时把常量放左边如if (5 x)这样误写成会直接编译报错从而提前发现。坑4浮点直接用比较前面运算符篇讲过浮点数有精度误差doublea0.10.2;if(a0.3){// ❌ 不成立a实际是0.30000000000000004System.out.println(相等);}正确做法判断差值是否小于某个极小值比如Math.abs(a - 0.3) 1e-6。坑5字符串比较用String 是引用类型比较的是内存地址不是内容。判断字符串相等要用equals()方法StringrolenewString(admin);if(roleadmin){// ❌ 大概率为 falseSystem.out.println(管理员);}if(admin.equals(role)){// ✅ 正确写法常量在前避免 NPESystem.out.println(管理员);}小技巧写字符串比较时把字面量放前面xxx.equals(var)这样即使 var 是 null 也不会抛空指针异常。四、if 的嵌套分支里再分支if 里面还能再套 if这是处理复杂逻辑的常用手段。比如先判断是否登录再判断是不是 VIPbooleanisLogintrue;booleanisVipfalse;if(isLogin){System.out.println(欢迎回来);if(isVip){System.out.println(尊贵的VIP会员您的专属权益已生效);}else{System.out.println(开通VIP享受更多特权哦);}}else{System.out.println(请先登录);}嵌套不宜过深一般建议不超过 3 层。嵌套太多代码会变成箭头形可读性骤降。遇到深层嵌套可以考虑① 提前 return 减少嵌套② 把内层逻辑抽成方法。后面讲方法时会详细讲。五、switch多路精准匹配if-else if-else 虽然万能但当分支条件都是拿一个变量跟几个固定值比时写起来很啰嗦。比如intweek3;if(week1)System.out.println(周一);elseif(week2)System.out.println(周二);elseif(week3)System.out.println(周三);// ...这种场景switch更清爽5.1 switch 基本语法switch(表达式){case值1:语句1;break;case值2:语句2;break;default:默认语句;break;}用星期的例子改写intweek3;switch(week){case1:System.out.println(周一开会);break;case2:System.out.println(周二写代码);break;case3:System.out.println(周三改Bug);break;// 命中这里case4:System.out.println(周四评审);break;case5:System.out.println(周五上线);break;case6:case7:System.out.println(周末休息);break;default:System.out.println(输入有误);break;}// 输出周三改Bug5.2 switch 支持哪些类型switch 对表达式的类型是有限制的不是所有类型都能用新手最容易在这里写错。类型分类支持的类型不支持基本类型byte / short / int / charlong / float / double / boolean包装类型Byte / Short / Integer / CharacterLong / Float / Double / Boolean引用类型StringJDK 7、enum 枚举其他普通对象老版本⚠️long/float/double/boolean 不能放进 switch写switch (x)时x 如果是 long/double 类型会直接编译报错。JDK 24 之前必须严格遵守。这也是面试常考题。5.3 case 穿透最经典的坑switch 的执行机制是先找到匹配的 case 标签然后从那一行开始一路往下执行直到遇到 break 或 switch 结束。如果漏写 break后面的 case 语句会被连带执行——这就叫case 穿透Fall-through。intn2;switch(n){case1:System.out.println(一);case2:System.out.println(二);// 匹配到这里case3:System.out.println(三);// ⚠️ 穿透了default:System.out.println(其他);}// 输出// 二// 三// 其他你以为只会输出二结果连着三其他全输出了——这是新人 switch 丢分最多的地方。记住每个 case 分支末尾习惯性加 break除非你明确要利用穿透特性。5.4 巧妙利用穿透合并 case穿透不全是坏事它有一种非常实用的用法多个 case 执行同一段代码时可以把它们摞在一起。比如判断月份属于哪个季节intmonth5;switch(month){case3:case4:case5:System.out.println(春季);break;case6:case7:case8:System.out.println(夏季);break;case9:case10:case11:System.out.println(秋季);break;case12:case1:case2:System.out.println(冬季);break;default:System.out.println(月份无效);}// 输出春季另一个常见例子同时处理大小写字母按 W/w 都向上。这种故意穿透是合法且推荐的。5.5 default 的作用default相当于 if-else 里的 else——所有 case 都不匹配时执行。它可以省略也可以放在 switch 的任意位置不一定非要最后但习惯上放末尾。⚠️default 放前面也要加 break如果 default 写在 case 前面且没加 break它会往下穿透到第一个 case 并继续执行结果往往不是你想要的。所以简单点default 永远放最后一行break 正常加。5.6 switch 与 StringJDK 7从 JDK 7 开始switch 支持 String 类型了比如根据操作指令做分发Stringcmdsave;switch(cmd){caseadd:System.out.println(新增);break;casesave:System.out.println(保存);break;casedel:System.out.println(删除);break;default:System.out.println(未知指令);}// 输出保存内部原理编译器会把字符串转成hashCode()equals()比较不是直接比地址所以能正确匹配内容。但要注意两点① 区分大小写“Save” 和 “save” 不同② 传入 null 会抛 NullPointerException建议先判空。六、if vs switch到底用哪个if 和 switch 都能做分支怎么选一张表说清楚对比维度if-elseswitch判断条件布尔表达式区间、大小、复杂逻辑固定常量值等值匹配适合场景范围判断、复杂组合条件菜单/状态/枚举等离散值匹配支持类型任意 boolean 表达式byte/short/int/char/String/enum代码可读性分支少时清爽嵌套多了变箭头多路分支时结构清晰、一目了然底层效率逐条判断分支越多越慢跳转表实现效率相对稳定一句话口诀等值匹配用 switch区间判断用 if能用 switch 的地方一定能用 if反过来不行。新手阶段优先掌握 ifswitch 当作等值匹配场景的语法糖即可。七、实战案例三个真实小练习案例1判断闰年规则能被 4 整除但不能被 100 整除或者能被 400 整除的是闰年。intyear2024;if((year%40year%100!0)||year%4000){System.out.println(year是闰年);}else{System.out.println(year是平年);}// 输出2024是闰年案例2简易计算器switch 版本输入两个数和一个运算符输出结果。inta10,b3;charop;switch(op){case:System.out.println(ab);break;case-:System.out.println(a-b);break;case*:System.out.println(a*b);break;case/:if(b0){System.out.println(除数不能为0);}else{System.out.println(a/b);}break;default:System.out.println(不支持的运算符);}案例3BMI 身体质量指数BMI 体重(kg) / 身高(m)²分级标准偏瘦18.5正常18.5-24偏胖24-28肥胖≥28。doubleweight70;// kgdoubleheight1.75;// mdoublebmiweight/(height*height);if(bmi18.5){System.out.println(偏瘦多吃点);}elseif(bmi24){System.out.println(正常继续保持);}elseif(bmi28){System.out.println(偏胖该运动了);}else{System.out.println(肥胖建议就医);}这里注意因为前面已经bmi 18.5不成立到else if (bmi 24)时自然就隐含了bmi 18.5所以不必写成bmi 18.5 bmi 24代码更简洁。八、避坑总结8 条血泪教训#坑点正确做法1if 条件写成非 boolean如if(a1)必须是 boolean比较用不用2省略大括号导致逻辑错位哪怕一条语句也加{ }3else 配对错误悬挂 else坚持写大括号缩进规范4多分支顺序写反导致被截胡严格→宽松顺序或写全上下界5浮点数用直接比较用Math.abs(a-b) epsilon6字符串用比较用equals()方法常量字面值在前7switch 漏写 break 导致穿透每个 case 末尾加 break故意穿透除外8switch 用 long/float/double/boolean只允许 byte/short/int/char/String/enum九、动手练习先自己写再对答案练习1三数最大值给定三个 int 变量 a、b、c用 if 找出其中最大的数并打印。提示可以用 “打擂台” 思想——先假设 a 最大再依次和 b、c 比较。练习2成绩等级switch 版输入 0-100 的分数输出对应等级90-100 优秀、80-89 良好、70-79 中等、60-69 及格、0-59 不及格。要求用 switch 实现。提示利用整数除法score / 10把分数映射成 0-10。练习3红绿灯模拟器定义一个 String 变量 color值为 red/yellow/green 之一用 switch 分别输出停“等一等”“行”其他值输出信号灯故障。注意处理 null。练习4个税计算器简易版假设月薪 taxSalary已扣五险一金按以下税率计税≤5000 免税5001-8000 部分 3%8001-17000 部分 10%17001-30000 部分 20%30000 部分 25%。用 if-else if 计算并输出税额。下篇预告 学完选择结构你已经能让程序做决定了。但很多事情还需要反复做——比如遍历 100 个学生成绩、从 1 加到 100、等待用户输入正确密码——这就要用到循环结构。下一篇我们讲 for / while / do-while 三种循环、break 与 continue 的区别、以及死循环的正确用法让你的程序真正跑起来。— 本文完 —