java中++/--的副作用在于求值时机不同:i++返回旧值后自增,++i先自增再返回新值;&&短路而&不短路,null时&会触发nullpointerexception;for-each遍历时删元素抛concurrentmodificationexception;string/enum switch有隐式空指针和分支覆盖要求。

Java中++和--的副作用到底在哪?
写i++还是++i,不只影响可读性,真会改出NullPointerException或错位计算。关键在表达式求值时机:前者返回旧值再自增,后者先自增再返回新值。
常见错误现象:list.get(i++)本想取第0个却跳过,或在while循环条件里混用导致索引多进一位。
- 数组遍历中优先用
++i(少一次拷贝,虽微但确定) - 当变量本身是方法调用结果(如
getCounter().increment())时,别直接套++——可能重复调用 - 在
switch表达式或return语句中用i++,等于悄悄扔掉刚算出的新值
Java布尔表达式里的&&和&不是性能差异问题,是逻辑安全问题
&&短路,&不短路——这点被当成“小技巧”,其实关系到空指针是否必然抛出。
使用场景:校验对象非空且满足某属性,比如user != null && user.isActive()。若换成&,user为null时仍会执行user.isActive(),直接NullPointerException。
立即学习“Java免费学习笔记(深入)”;
- 数据库查询条件拼接时,用
&&可避免对null的toString()调用 -
Optional链式调用中混用&,会让isPresent()之后的get()失去保护 - 自定义
boolean方法含IO或耗时操作(如isFileValid()),用&等于强制执行所有判断,白耗资源
for-each循环为什么不能删元素?
因为底层用的是Iterator,而for-each隐藏了迭代器对象,删元素会触发ConcurrentModificationException——这不是并发问题,单线程也炸。
错误现象:for (String s : list) { if (s.isEmpty()) list.remove(s); }运行时报java.util.ConcurrentModificationException。
- 真要边遍历边删,用显式
Iterator并调用it.remove() - 批量删除优先用
removeIf()(JDK 8+),它内部已处理modCount同步 - 数组型集合(如
ArrayList)大量删除时,倒序for循环比Iterator更省内存(避免元素前移开销)
switch从int到String再到enum,编译器干了什么?
Java 7 支持String,本质是编译器帮你转成hashCode() + equals()双重校验;Java 14+支持switch表达式,返回值必须覆盖所有分支,否则编译失败。
容易踩的坑:用String做switch时,如果传入null,会直接NullPointerException——没有隐式null分支。
- 枚举
switch推荐加default分支(哪怕抛AssertionError),防止新增枚举值后逻辑静默失效 -
switch表达式中每个case必须有->或:+break,混用会编译报错 - 字符串
switch性能接近if-else链,别迷信“更快”——除非分支极多且字符串固定
最常被忽略的其实是switch表达式的类型推导规则:当分支返回不同类型(比如Integer和String),编译器会尝试找最小公共父类,有时得到Object而不是你预期的String。










