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

结合场景再看三个关注点

  1. 短路保护obj != null && obj.isActive() 是惯用防 NPE 模式。
  2. 整数除法会吞小数,促销/均分要显式策略。
  3. 字符串 + 改变后续运算的类型与顺序,日志拼接要清醒。

核心概念与准确模型

1. 常用类别

类别例子注意
算术+ - * / %整除截断;溢出环绕
复合赋值+= *=隐含转换规则
比较== != < >基本类型比值;引用比引用
逻辑短路&& ||可能跳过右操作数
逻辑非短路& |(布尔时)两侧都算
三元c ? a : b两端类型需兼容
位运算& | ^ ~ << >> >>>协议/标志位
instanceofx instanceof Type模式匹配形态随版本增强

2. 数值提升(直觉)

  • 小于 int 的类型在许多算术中提升到 int
  • intlong 混合 → long
  • 浮点参与 → 向浮点提升

3. 优先级

不要靠背诵全表写业务:

  • 乘除优先于加减
  • 比较优先于逻辑与
  • 不确定就加括号,给读者看意图

4. == 对引用

  • 比较是否同一对象引用(或同一基本值)
  • 字符串内容比较用 equals(并注意 null 安全)
  • 详解见 equals 与 hashCode

边界情况与反直觉行为

  1. % 与负数:符号规则要测,不要想当然。
  2. >>> 无符号右移>> 算术右移不同。
  3. 浮点比较== 对计算结果不可靠。
  4. 自增作表达式 i++ vs ++i 的值不同。

常见误区

[!warning] 常见误区:用 & 做空安全判断 错误理解:obj != null & obj.flag 一样安全。
正确模型:& 两侧都求值,仍可能 NPE;用 &&
为何易错:位运算与逻辑运算符号重叠。

工程实践

  1. 复杂条件拆成命名布尔局部变量。
  2. 金额/比例计算写单测。
  3. 位运算集中在基础设施编解码,不散落业务。
  4. 日志优先 format 或日志框架参数化,减少 + 迷雾。

本节总结

  • 表达式 = 运算符 + 操作数 + 类型规则
  • 短路、提升、优先级是三条主线
  • 括号与命名条件提升可维护性

自测题

  1. 为何 onShelf && stock>=want 比先算库存再与更合适(当右式昂贵或有副作用时)?
  2. byte a=1; byte b=2; byte c=a+b; 为何常需强转?
参考答案
  1. 短路可跳过昂贵/不安全的右操作数。
  2. a+b 提升为 int,赋回 byte 要显式转换。

延伸阅读与资料来源

资料类型支撑内容
JLS Expressions规范表达式与运算符
创建于 2026/7/15 更新于 2026/7/15