Java 运算符与表达式
Java 运算符、优先级、结合性、短路求值与数值提升:表达式如何得到类型化的值。
#type / concept
#status / growing
#tech / dev
#resource / java
[!info] 关联笔记
Java 运算符与表达式
这个概念为什么出现
控制流、校验与计算都建立在表达式上。若优先级、短路与数值提升不清楚,会出现:
a + b + "x"拼接顺序意外&&与&混用导致空指针byte运算后无法直接赋回byte
[!abstract] 一句话理解 表达式在类型规则下求值;算术有提升与溢出,布尔逻辑常用短路运算符,优先级可用括号显式化,对象相等比较要区分引用
==与业务equals。
最小可运行示例
先把示例放进业务场景,再看代码:
场景:促销服务判断是否包邮并计算应付件数
规则:在售且库存 ≥ 下单量才可售;重量超过阈值则不可静默默认包邮。
教学点:短路、比较、算术、括号。
public class ShippingRule {
// canFulfill:判断库存是否够扣。
//
// 业务意图:缺货或已下架时不能下单。
// 教学点:&& 短路——左侧 false 时不评估右侧。
static boolean canFulfill(boolean onShelf, int stock, int want) {
// 若 onShelf 为 false,不会执行 stock >= want(本例无副作用,但模式重要)。
return onShelf && stock >= want;
}
// billableUnits:把“买 M 赠 1”粗算成计费件数(示例规则)。
static int billableUnits(int want) {
// 整数除法截断:赠品按组计算。
int giftGroups = want / 3;
return want - giftGroups;
}
public static void main(String[] args) {
System.out.println(canFulfill(true, 10, 3)); // true
System.out.println(canFulfill(false, 10, 3)); // false
System.out.println(billableUnits(4)); // 4 - 1 = 3
String sku = "SKU";
// + 左结合:先 1+2 得 3,再和字符串拼接。
System.out.println(1 + 2 + sku); // 3SKU
// 先字符串拼接再加:12SKU
System.out.println("" + 1 + 2 + sku);
}
}
建议运行:
javac ShippingRule.java && java ShippingRule
期望输出:
true
false
3
3SKU
12SKU
结合场景再看三个关注点
- 短路保护:
obj != null && obj.isActive()是惯用防 NPE 模式。 - 整数除法会吞小数,促销/均分要显式策略。
- 字符串
+改变后续运算的类型与顺序,日志拼接要清醒。
核心概念与准确模型
1. 常用类别
| 类别 | 例子 | 注意 |
|---|---|---|
| 算术 | + - * / % | 整除截断;溢出环绕 |
| 复合赋值 | += *= | 隐含转换规则 |
| 比较 | == != < > | 基本类型比值;引用比引用 |
| 逻辑短路 | && || | 可能跳过右操作数 |
| 逻辑非短路 | & |(布尔时) | 两侧都算 |
| 三元 | c ? a : b | 两端类型需兼容 |
| 位运算 | & | ^ ~ << >> >>> | 协议/标志位 |
| instanceof | x instanceof Type | 模式匹配形态随版本增强 |
2. 数值提升(直觉)
- 小于
int的类型在许多算术中提升到int int与long混合 →long- 浮点参与 → 向浮点提升
3. 优先级
不要靠背诵全表写业务:
- 乘除优先于加减
- 比较优先于逻辑与
- 不确定就加括号,给读者看意图
4. == 对引用
- 比较是否同一对象引用(或同一基本值)
- 字符串内容比较用
equals(并注意 null 安全) - 详解见 equals 与 hashCode
边界情况与反直觉行为
%与负数:符号规则要测,不要想当然。>>>无符号右移 与>>算术右移不同。- 浮点比较:
==对计算结果不可靠。 - 自增作表达式
i++vs++i的值不同。
常见误区
[!warning] 常见误区:用 & 做空安全判断 错误理解:
obj != null & obj.flag一样安全。
正确模型:&两侧都求值,仍可能 NPE;用&&。
为何易错:位运算与逻辑运算符号重叠。
工程实践
- 复杂条件拆成命名布尔局部变量。
- 金额/比例计算写单测。
- 位运算集中在基础设施编解码,不散落业务。
- 日志优先
format或日志框架参数化,减少+迷雾。
本节总结
- 表达式 = 运算符 + 操作数 + 类型规则
- 短路、提升、优先级是三条主线
- 括号与命名条件提升可维护性
自测题
- 为何
onShelf && stock>=want比先算库存再与更合适(当右式昂贵或有副作用时)? byte a=1; byte b=2; byte c=a+b;为何常需强转?
参考答案
- 短路可跳过昂贵/不安全的右操作数。
a+b提升为int,赋回byte要显式转换。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| JLS Expressions | 规范 | 表达式与运算符 |