# if / else:判断库存
学习目标:用相同库存规则理解各语言的条件、分支顺序与表达式差异。
前置知识:变量、整数比较与标准输出。范围:只讨论已校验库存的展示逻辑。
# 问题与边界
商品详情页根据当前库存显示一条提示。输入是已经完成校验的非负整数:
| 库存 | 输出 |
|---|---|
| 0 | sold out |
| 1~5 | low stock |
| 大于 5 | in stock |
这里展示页面提示,不处理实际扣库存。真实下单还涉及并发与数据一致性,不能靠这段判断保证。
stock <= 5 不是独立的“1~5”判断:前面的 stock == 0 已排除 0,输入的非负整数前置条件又排除了负数,因此走到第二分支时它才等价于 1~5。分支从上到下选择,最多执行一个分支。
# 关键差异
| 语言 | 条件类型 | if 本身是否产值 |
块语法 |
|---|---|---|---|
| Rust | bool |
是,值分支须类型兼容 | 大括号必需,条件无须圆括号 |
| Go | 布尔类型 | 否 | 大括号必需,条件无须圆括号 |
| Java | boolean 或可拆箱的 Boolean |
否 | 条件用圆括号;本文总保留大括号 |
| JavaScript / TypeScript | 按真值规则转换 | 否 | 条件用圆括号;本文总保留大括号 |
| Kotlin | Boolean |
是,用作值时须有 else |
条件用圆括号;本文总保留大括号 |
| Python | 按真值规则判断 | 否,条件表达式是另一种语法 | 冒号与缩进 |
| C++ | 可按上下文转换为 bool |
否 | 条件用圆括号;本文总保留大括号 |
Java 的 null 拆箱会抛异常,不是合法的业务条件。本文统一显式比较库存,不依赖数字的真值规则。
# 各语言实现
下面八个代码块分别是独立完整程序,不需互相拼接;库存为 3 时预期输出 low stock。版本与执行情况见验证记录。
# Rust
Rustfn main() {
let stock = 3;
if stock == 0 {
println!("sold out");
} else if stock <= 5 {
println!("low stock");
} else {
println!("in stock");
}
}
条件不需要圆括号,分支使用大括号。Rust 要求条件是布尔值。
# Go
Gopackage main
import "fmt"
func main() {
stock := 3
if stock == 0 {
fmt.Println("sold out")
} else if stock <= 5 {
fmt.Println("low stock")
} else {
fmt.Println("in stock")
}
}
:= 声明局部变量并推断类型。这里的 else 与前一个右大括号在同一行,符合 Go 的自动分号规则。参见 Go 规范。
# Java
使用 JDK 21。
Javapublic class Main {
public static void main(String[] args) {
int stock = 3;
if (stock == 0) {
System.out.println("sold out");
} else if (stock <= 5) {
System.out.println("low stock");
} else {
System.out.println("in stock");
}
}
}
条件使用圆括号。即使分支只有一条语句,也统一保留大括号,便于后续修改。参见 Java 条件语句教程。
# JavaScript
JavaScriptconst stock = 3;
if (stock === 0) {
console.log("sold out");
} else if (stock <= 5) {
console.log("low stock");
} else {
console.log("in stock");
}
这里用 === 比较数值,不让相等判断先做隐式类型转换。条件表达式最终按 ECMAScript 的布尔转换规则判断;参见 ECMAScript if 语句。
# TypeScript
TypeScriptconst stock: number = 3;
if (stock === 0) {
console.log("sold out");
} else if (stock <= 5) {
console.log("low stock");
} else {
console.log("in stock");
}
这里显式写出 number 供对照,实际通常可以推断。类型标注不会替外部输入做运行时校验;条件判断沿用 JavaScript 的运行时语义。参见 TypeScript 收窄说明。
# Kotlin
Kotlinfun main() {
val stock = 3
if (stock == 0) {
println("sold out")
} else if (stock <= 5) {
println("low stock")
} else {
println("in stock")
}
}
val 表示绑定不能重新赋值。Kotlin 的 if 也可产生结果值,见 Kotlin 条件与循环。
# Python
Pythonstock = 3
if stock == 0:
print("sold out")
elif stock <= 5:
print("low stock")
else:
print("in stock")
缩进界定代码块,多分支使用 elif。参见 Python 控制流教程。
# C++
C++#include <iostream>
int main() {
const int stock = 3;
if (stock == 0) {
std::cout << "sold out\n";
} else if (stock <= 5) {
std::cout << "low stock\n";
} else {
std::cout << "in stock\n";
}
}
这里显式比较数值,避免将“非零”误当成业务条件。条件转换规则见 C++ 工作草案:选择语句。该链接是流动工作草案,不是 C++17 版本兼容性证明。
# 当分支只是选择一个值
如果只是根据调试开关选择日志级别,可以简化表达。下表是函数内部的替换片段,不是独立程序,也不替换上述库存的三个分支。先在所在语言的函数内声明布尔变量 debug(例如 Rust 的 let debug = true;),再放入对应片段,最后用该语言的输出语句打印 level。true 预期得到 debug,false 预期得到 info(Python 使用 True / False)。这里说明“二选一取值”,库存例子则说明“按顺序执行三个互斥分支”;不要为了套三元语法把后者改成难读的嵌套表达式。
| 语言 | 写法 |
|---|---|
| Rust | let level = if debug { "debug" } else { "info" }; |
| Go | level := "info",随后通过 if debug { level = "debug" } 更新 |
| Java | String level = debug ? "debug" : "info"; |
| JS / TS | const level = debug ? "debug" : "info"; |
| Kotlin | val level = if (debug) "debug" else "info" |
| Python | level = "debug" if debug else "info" |
| C++ | const char* level = debug ? "debug" : "info"; |
Go 在这个例子里用默认值加条件赋值即可,不需要创建映射表或匿名函数来模拟三元表达式。
# 迁移误区与适用限制
if stock不能跨语言照搬。它也无法表达“库存是否低于阈值”。- 本例假定库存非负。如果负数可能进入系统,应在输入边界处理,不要让它落入“库存不足”的正常分支。
- 不要为了减少行数,把有副作用的多步操作挤进条件表达式。
# 运行与验证
语言与版本基线见主题首页。每种语言使用独立目录,按对应小节保存并运行。
将完整程序的 stock 初值依次替换为 0、1、3、5、6,每次按原命令重新编译或运行:
| 库存 | 预期输出 |
|---|---|
| 0 | sold out |
| 1 | low stock |
| 3 | low stock |
| 5 | low stock |
| 6 | in stock |
这些是验证步骤与预期,不代表本次已经执行;实际记录见运行与验证。负数不属于本例输入契约,应由输入边界拒绝。