欢迎光临
我们一直在努力

第5章 条件判断:让程序根据规则做选择

第5章 条件判断:让程序根据规则做选择

前面我们已经能读取用户输入,也能保存变量。但程序如果只会从上到下一行行执行,能力仍然很有限。

真实业务里到处都是选择:

  • 年龄够不够 18 岁?
  • 用户是否登录?
  • 密码是否正确?
  • 商品库存是否足够?
  • 成绩是否及格?
  • 订单是否可以取消?

条件判断的意义,就是让程序根据不同情况走不同分支。

一、最基本的 if

int age = 20;

if (age >= 18) {
System.out.println("可以注册");
}

if 后面的条件必须是 boolean。条件为 true,执行大括号里的代码;条件为 false,跳过。

流程:

#mermaid-svg-hbFbEFxrMzyDfCMe{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hbFbEFxrMzyDfCMe .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hbFbEFxrMzyDfCMe .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hbFbEFxrMzyDfCMe .error-icon{fill:#552222;}#mermaid-svg-hbFbEFxrMzyDfCMe .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hbFbEFxrMzyDfCMe .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hbFbEFxrMzyDfCMe .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hbFbEFxrMzyDfCMe .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hbFbEFxrMzyDfCMe .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hbFbEFxrMzyDfCMe .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hbFbEFxrMzyDfCMe .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hbFbEFxrMzyDfCMe .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hbFbEFxrMzyDfCMe .marker.cross{stroke:#333333;}#mermaid-svg-hbFbEFxrMzyDfCMe svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hbFbEFxrMzyDfCMe p{margin:0;}#mermaid-svg-hbFbEFxrMzyDfCMe .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-hbFbEFxrMzyDfCMe .cluster-label text{fill:#333;}#mermaid-svg-hbFbEFxrMzyDfCMe .cluster-label span{color:#333;}#mermaid-svg-hbFbEFxrMzyDfCMe .cluster-label span p{background-color:transparent;}#mermaid-svg-hbFbEFxrMzyDfCMe .label text,#mermaid-svg-hbFbEFxrMzyDfCMe span{fill:#333;color:#333;}#mermaid-svg-hbFbEFxrMzyDfCMe .node rect,#mermaid-svg-hbFbEFxrMzyDfCMe .node circle,#mermaid-svg-hbFbEFxrMzyDfCMe .node ellipse,#mermaid-svg-hbFbEFxrMzyDfCMe .node polygon,#mermaid-svg-hbFbEFxrMzyDfCMe .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hbFbEFxrMzyDfCMe .rough-node .label text,#mermaid-svg-hbFbEFxrMzyDfCMe .node .label text,#mermaid-svg-hbFbEFxrMzyDfCMe .image-shape .label,#mermaid-svg-hbFbEFxrMzyDfCMe .icon-shape .label{text-anchor:middle;}#mermaid-svg-hbFbEFxrMzyDfCMe .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hbFbEFxrMzyDfCMe .rough-node .label,#mermaid-svg-hbFbEFxrMzyDfCMe .node .label,#mermaid-svg-hbFbEFxrMzyDfCMe .image-shape .label,#mermaid-svg-hbFbEFxrMzyDfCMe .icon-shape .label{text-align:center;}#mermaid-svg-hbFbEFxrMzyDfCMe .node.clickable{cursor:pointer;}#mermaid-svg-hbFbEFxrMzyDfCMe .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hbFbEFxrMzyDfCMe .arrowheadPath{fill:#333333;}#mermaid-svg-hbFbEFxrMzyDfCMe .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hbFbEFxrMzyDfCMe .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hbFbEFxrMzyDfCMe .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hbFbEFxrMzyDfCMe .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hbFbEFxrMzyDfCMe .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hbFbEFxrMzyDfCMe .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hbFbEFxrMzyDfCMe .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hbFbEFxrMzyDfCMe .cluster text{fill:#333;}#mermaid-svg-hbFbEFxrMzyDfCMe .cluster span{color:#333;}#mermaid-svg-hbFbEFxrMzyDfCMe div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hbFbEFxrMzyDfCMe .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hbFbEFxrMzyDfCMe rect.text{fill:none;stroke-width:0;}#mermaid-svg-hbFbEFxrMzyDfCMe .icon-shape,#mermaid-svg-hbFbEFxrMzyDfCMe .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hbFbEFxrMzyDfCMe .icon-shape p,#mermaid-svg-hbFbEFxrMzyDfCMe .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hbFbEFxrMzyDfCMe .icon-shape .label rect,#mermaid-svg-hbFbEFxrMzyDfCMe .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hbFbEFxrMzyDfCMe .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hbFbEFxrMzyDfCMe .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hbFbEFxrMzyDfCMe :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

true

false

age=20

age >= 18?

输出可以注册

跳过

Java 不允许把数字直接当条件:

int count = 1;
// if (count) { } // 错误

必须明确:

if (count > 0) {
System.out.println("有数据");
}

这能减少模糊判断。

二、if else:两条路选一条

int age = 16;

if (age >= 18) {
System.out.println("可以注册");
} else {
System.out.println("未满18岁,不能注册");
}

这就是二选一。

常见场景:

boolean isLogin = false;

if (isLogin) {
System.out.println("进入首页");
} else {
System.out.println("跳转登录页");
}

条件判断要读起来像业务规则。变量名越清楚,if 越好懂。

不清楚:

boolean flag = true;

if (flag) {
}

清楚:

boolean hasPermission = true;

if (hasPermission) {
}

三、else if:多分支判断

成绩等级:

int score = 85;

if (score >= 90) {
System.out.println("优秀");
} else if (score >= 80) {
System.out.println("良好");
} else if (score >= 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}

程序会从上到下判断,命中第一个满足的分支后,就不会继续判断后面的分支。

所以顺序非常重要。

错误顺序:

if (score >= 60) {
System.out.println("及格");
} else if (score >= 90) {
System.out.println("优秀");
}

score 是 95 时,第一个条件已经满足,输出“及格”,永远到不了“优秀”。

多分支判断要把更具体、更严格的条件放前面。

四、先校验合法性,再做业务判断

成绩不能小于 0,也不能大于 100。真实程序要先校验数据是否合法。

int score = 120;

if (score < 0 || score > 100) {
System.out.println("分数不合法");
} else if (score >= 90) {
System.out.println("优秀");
} else if (score >= 80) {
System.out.println("良好");
} else if (score >= 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}

如果不先校验,120 会被判断成“优秀”,这显然不符合业务。

这个顺序很重要:

先判断输入能不能用
-> 再判断业务属于哪一种情况

以后处理用户输入、网络返回、文件内容都一样。

五、逻辑运算符

&&

&& 表示并且。

boolean canRegister = age >= 18 && hasPhone;

两个条件都为 true,结果才为 true。

||

|| 表示或者。

if (score < 0 || score > 100) {
System.out.println("分数不合法");
}

只要一个条件为 true,结果就是 true。

!

! 表示取反。

if (!isLogin) {
System.out.println("请先登录");
}

复杂条件可以拆变量:

boolean validAge = age >= 18 && age <= 120;
boolean validPhone = phone != null && phone.length() == 11;
boolean canRegister = validAge && validPhone;

if (canRegister) {
System.out.println("可以注册");
}

不要把所有条件塞进一行,读起来会很累。

六、短路:后面的条件可能不会执行

&& 和 || 有短路特性。

String name = null;

if (name != null && name.length() > 0) {
System.out.println("姓名有效");
}

如果 name != null 是 false,后面的 name.length() 不会执行,所以不会空指针。

如果写反:

if (name.length() > 0 && name != null) {
}

会先执行 name.length(),直接空指针。

所以判断 null 要放在前面。

|| 也会短路:

if (name == null || name.isEmpty()) {
System.out.println("姓名为空");
}

name 为 null 时,后面的 isEmpty() 不会执行。

七、嵌套 if 和提前返回

不推荐层层嵌套:

if (age >= 18) {
if (phone != null && phone.length() == 11) {
if (agreeTerms) {
System.out.println("注册成功");
}
}
}

嵌套一多,读者要在脑子里记住很多层条件。

更清楚的写法是提前返回:

if (age < 18) {
System.out.println("未满18岁");
return;
}

if (phone == null || phone.length() != 11) {
System.out.println("手机号不合法");
return;
}

if (!agreeTerms) {
System.out.println("请先同意协议");
return;
}

System.out.println("注册成功");

这种写法特别适合校验流程:

不满足条件就直接结束
全部通过才进入主逻辑

八、switch:固定值分支

菜单选择适合 switch:

int command = 2;

switch (command) {
case 1:
System.out.println("查询余额");
break;
case 2:
System.out.println("充值");
break;
case 3:
System.out.println("消费");
break;
case 0:
System.out.println("退出");
break;
default:
System.out.println("未知命令");
break;
}

break 用来结束当前 case。如果不写,可能继续执行后面的 case。

switch 适合:

  • 菜单命令。
  • 固定状态码。
  • 星期。
  • 固定枚举值。

不适合:

  • 范围判断,比如分数等级。
  • 多个复杂条件组合。
  • 每个分支代码很长。

九、字符串也可以 switch

String role = "admin";

switch (role) {
case "admin":
System.out.println("管理员");
break;
case "user":
System.out.println("普通用户");
break;
default:
System.out.println("未知角色");
break;
}

如果 role 可能是 null,要先判断:

if (role == null) {
System.out.println("角色为空");
return;
}

switch (role) {
case "admin":
System.out.println("管理员");
break;
default:
System.out.println("未知角色");
break;
}

对 null 做 switch 会空指针。

十、条件判断实战:注册校验

需求:

  • 姓名不能为空。
  • 年龄必须 18 到 120。
  • 手机号必须 11 位,并且以 1 开头。
  • 必须同意协议。

代码:

public class RegisterCheckDemo {
public static void main(String[] args) {
String name = "小林";
int age = 20;
String phone = "13800000000";
boolean agreeTerms = true;

if (name == null || name.isEmpty()) {
System.out.println("姓名不能为空");
return;
}

if (age < 18 || age > 120) {
System.out.println("年龄不符合要求");
return;
}

if (phone == null || phone.length() != 11 || !phone.startsWith("1")) {
System.out.println("手机号不合法");
return;
}

if (!agreeTerms) {
System.out.println("请先同意协议");
return;
}

System.out.println("注册成功");
}
}

这段代码没有复杂语法,但它体现了重要习惯:

  • 外部数据先校验。
  • 每个失败原因明确。
  • 使用提前 return 降低嵌套。
  • 主成功逻辑放在最后。

十一、条件判断实战:订单状态

需求:

  • 未支付订单可以取消。
  • 已支付订单不能直接取消,需要走退款。
  • 已发货订单不能取消。
  • 已取消订单不能重复取消。

代码:

public class OrderStatusDemo {
public static void main(String[] args) {
String status = "PAID";

if (status == null) {
System.out.println("订单状态异常");
return;
}

switch (status) {
case "CREATED":
System.out.println("订单已取消");
break;
case "PAID":
System.out.println("订单已支付,请申请退款");
break;
case "SHIPPED":
System.out.println("订单已发货,不能取消");
break;
case "CANCELLED":
System.out.println("订单已经取消,不能重复操作");
break;
default:
System.out.println("未知订单状态:" + status);
break;
}
}
}

这比用很多散乱 if 更清楚,因为状态是固定值。

十二、常见错误

1. 把 = 当成比较

Java 中:

int age = 18;

是赋值。

比较相等用:

age == 18

2. 字符串用 ==

if (role == "admin") {
}

应该:

if ("admin".equals(role)) {
}

3. 忘记 null 判断顺序

if (name.length() > 0 && name != null) {
}

应先判断 null。

4. 条件顺序错误

分数等级中先判断 >=60,后面优秀永远到不了。

5. switch 忘记 break

除非明确需要穿透,否则 case 后写 break。

十三、本章练习

  • 写成绩等级判断,要求先判断分数是否合法。

  • 写会员等级判断:

    • 消费 >= 10000:钻石。
    • = 5000:黄金。

    • = 1000:白银。

    • 否则普通。
  • 写登录判断:
    • 用户名不能为空。
    • 密码不能为空。
    • 用户名是 admin 且密码是 123456,登录成功。
    • 否则登录失败。
  • 写订单取消判断,至少包含 CREATED、PAID、SHIPPED、CANCELLED。

  • 把一个三层嵌套 if 改成提前返回。

  • 十四、本章总结

    条件判断是业务规则的基础。

    你需要掌握:

    • if 用来判断条件是否成立。
    • else 处理不成立的情况。
    • else if 处理多个分支。
    • 多分支判断顺序很重要。
    • 先校验合法性,再做业务判断。
    • &&、|| 有短路特性。
    • null 判断要放在可能调用方法之前。
    • 提前返回可以减少嵌套。
    • switch 适合固定值分支。
    • 字符串比较用 equals。

    写条件判断时,不要只问“语法对不对”,还要问“业务规则有没有表达清楚”。代码最终是给业务服务的。

    赞(0)
    未经允许不得转载:171主机测评 » 第5章 条件判断:让程序根据规则做选择
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址