
自增自减运算符写在变量前还是后,结果真不一样
Java里++i和i++不是等价的,区别在「表达式的值」——前者返回自增后的值,后者返回自增前的值。很多人只记“前++先加后用,后++先用后加”,但没意识到这直接影响赋值、循环条件、甚至方法参数求值顺序。
- 在
int a = i++;中,a拿到的是旧值,i才变 - 在
int b = ++j;中,j先加1,b拿到新值 - 用在
for循环里(如for (int i = 0; i )看似安全,但一旦混进复杂表达式(比如<code>arr[i++] = ++count),执行顺序就容易出错 - JVM按从左到右求值,但自增/自减的副作用发生时机紧贴其所在位置,不是统一延后
在for循环里用i++还是++i?性能有差别吗
单纯作为循环步进语句时,i++和++i生成的字节码完全一样(JDK 8+,HotSpot JVM)。编译器做了优化:当表达式值被丢弃时,两者无差异。
- 反例:
for (int i = 0; i —— 这里用<code>i++或++i效果一致,别为“效率”强行改 - 但若写成
while (i++ ,逻辑就和<code>while (++i 不同了,边界行为会偏移1 - 不要依赖“前缀更快”的直觉;真正影响性能的是重复调用
list.size()这种开销,而不是自增写法
++用在布尔值、字符串或对象上会报错
Java的自增自减只支持数值类型(byte、short、char、int、long、float、double),且不支持自动装箱后的包装类(如Integer)直接参与运算。
-
boolean flag = true; flag++;→ 编译错误:bad operand type boolean for unary operator '++' -
String s = "a"; s++;→ 编译错误,字符串不可自增 -
Integer x = 5; x++;看似能过,其实是自动拆箱→自增→重新装箱,但若x为null,运行时抛NullPointerException - 数组长度、集合大小等是只读属性,
arr.length++或list.size()++直接编译失败
复合赋值+自增混用时,注意优先级和副作用时机
像i += ++i + i++这类表达式,表面看是数学运算,实际是未定义行为的温床——不是Java规范不允许,而是它明确要求“操作数从左到右求值”,但各子表达式的副作用(即i的变化)穿插其中,极易误判。
立即学习“Java免费学习笔记(深入)”;
- 例如:
int i = 1; int j = i++ + ++i;→ 先取i旧值1(i++部分),i变为2; → 再执行++i,i变3并取3; → 所以j = 1 + 3 == 4,i == 3 - 但换成
i = i++ + ++i;,结果仍是4,而i最终是3 —— 不要指望靠“多试几次”来验证,应避免这种写法 - 真实项目里出现这类代码,99% 是可读性灾难,也难调试;用临时变量拆解更安全
最常被忽略的点是:自增自减的副作用发生在整个表达式求值过程中的具体位置,而不是“语句结束时”。哪怕只是多嵌套一层方法调用或三元运算,都可能让执行顺序变得反直觉。写的时候手快,读的时候得逐行推导字节码逻辑。











