Java包装类(如Integer、Long)是不可变对象,因其内部值由private final字段封装且无修改方法,故天然线程安全,可安全共享于多线程环境,无需同步。

Java 中的包装类(如 Integer、Long、Boolean 等)是典型的不可变对象,其线程安全优势直接源于“状态不可变”这一本质特性,无需额外同步即可在多线程中安全共享。
包装类为什么是不可变的
每个包装类内部都用 final 字段封装基本类型值,且不提供任何修改该值的方法:
- Integer 类中只有 private final int value;
- 构造后无法改变 value,所有“修改”操作(如 +、-、intValue() 后再赋值)都返回新对象
- 没有 setter、没有字段暴露、类本身被声明为 final,无法继承或篡改行为
不可变性如何直接带来线程安全
多个线程同时读取同一个 Integer 实例时,不会出现竞态条件或中间状态问题:
- 读操作无副作用,JVM 可自由缓存字段值(如通过 volatile 或 CPU 缓存优化)
- 不存在“写-读”冲突:因为根本没有写操作,所以不需要 synchronized、Lock 或 volatile 修饰
- 发布安全:只要对象构造完成(无 this 逃逸),其他线程看到的一定是完整、一致的状态
对比可变对象的典型风险
如果用可变容器(如 AtomicInteger)替代包装类来传递数值,在某些场景下反而需额外同步:
立即学习“Java免费学习笔记(深入)”;
- AtomicInteger 允许 incrementAndGet(),但若业务逻辑需要“读-改-写”复合操作(如先判断再更新),仍可能出错
- 而 Integer 一旦传入方法参数或放入 Map 键中,值就固定了,不会被意外修改
- 例如:Map
的 key 用 Integer 安全;若误用可变对象作 key,后续修改会导致 hashcode 变化,查不到原值
实际使用中的关键注意事项
不可变性虽强,但需避免常见误用:
- 不要混淆“对象不可变”和“引用不可变”:Integer i = 10; i = 20; 这里是引用指向新对象,原对象未变
- 自动装箱/拆箱不影响不可变性,但要注意缓存范围(如 Integer.valueOf(127) 返回缓存实例,valueOf(128) 每次新建)
- 在高并发计数等场景,别因“不可变”就硬套 Integer——它不适合频繁变更;此时应选 AtomicInteger 或 LongAdder


















