Java运算符优先级不决定执行顺序,真正控制求值时机的是从左到右的操作数求值顺序、结合性及短路特性;例如method1()+method2()*method3()必先调用method1(),再method2(),最后method3()。

Java运算符优先级不是“从高到低依次执行”
很多人误以为只要记住优先级表,就能直接按顺序算表达式。其实不然:+ 和 * 的优先级差异确实决定 a + b * c 等价于 a + (b * c);但优先级不等于执行顺序,更不决定求值时机。真正控制“谁先算”的是结合性(left/right)和操作数求值顺序——Java明确规定:所有操作数从左到右依次求值,与运算符优先级无关。
比如:
method1() + method2() * method3(),即使
* 优先级高于 +,也一定是先调用 method1(),再 method2(),最后 method3();乘法运算发生在三个方法都返回之后。
赋值类运算符(=、+=等)的右结合性容易被忽略
=、+=、-= 等是右结合的,这意味着多个赋值连写时,从右往左解析:
-
a = b = c等价于a = (b = c),先执行b = c(返回c的值),再赋给a -
a += b += c等价于a += (b += c),b += c先完成并返回新值,再加到a上 - 若
c是表达式(如getCount()),它只被求值一次,且在最内层赋值前完成
常见陷阱:int a = 0, b = 0; a = b = 1 + 2; 中,1 + 2 只算一次,结果是 a == 3 且 b == 3;但若写成 a = b = getCount();,getCount() 也仅执行一次。
立即学习“Java免费学习笔记(深入)”;
逻辑运算符 && 和 || 的短路特性会跳过部分求值
它们优先级低于关系运算符(如 、==),但关键在于:一旦左操作数已能确定整个表达式结果,右操作数完全不求值。
-
obj != null && obj.toString().length() > 0:如果obj为null,obj.toString()根本不会执行,避免空指针 -
isReady() || initialize():若isReady()返回true,initialize()不会被调用 - 注意:
&和|(位运算符)无短路行为,左右操作数总会求值,慎用于含副作用的表达式
短路不改变优先级——a d || e == f 仍按 、>、== → && → || 分组,但求值过程可能提前终止。
自增/自减(++、--)的位置影响值的使用时机
前置(++i)和后置(i++)不仅语法不同,语义上根本就是两个操作:前者返回递增后的值,后者返回递增前的副本。而这个“返回值”参与的是整个表达式的计算,不是最终赋值目标。
-
int i = 1; int j = i++ + ++i;:执行顺序是 —— 取i当前值(1)用于加法左操作数,然后i变为 2;接着++i将i变为 3 并返回 3;最终j = 1 + 3 == 4,i == 3 - 不要依赖多处修改同一变量的复合表达式,JLS 明确说明其行为由求值顺序保证,但可读性差、易出错
- 编译器不会重排这类表达式;Java 严格按从左到右求操作数、再按优先级和结合性执行运算
真正复杂的地方不在优先级表本身,而在「操作数求值」和「运算执行」这两个阶段的分离——多数 bug 出现在混淆了这两者。










