AtomicIntegerFieldUpdater仅支持public volatile int字段,不支持private或protected字段,即使在继承关系中也无法绕过访问限制,因其反射获取Field时严格校验声明类中的实际修饰符。

AtomicIntegerFieldUpdater 不能直接更新 private 或 protected 字段,无论是否在子类中,它只支持 public volatile int 字段。
字段必须是 public volatile
AtomicIntegerFieldUpdater 的设计要求被操作的字段必须满足三个条件:是 int 类型、声明为 volatile、且具有 public 访问权限。即使字段在父类中声明为 protected,子类也无法通过 updater 修改它——因为 updater 在运行时通过反射获取字段时会检查其实际修饰符,private/protected 字段会直接抛出 RuntimeException(通常是 IllegalArgumentException,提示“Must be public”)。
- 哪怕子类继承了父类的 protected 字段,updater 构造时传入的类参数(如
AtomicIntegerFieldUpdater.newUpdater(Parent.class, "field"))仍需该字段在Parent.class中是 public - 如果字段是 protected,即使子类能访问它,updater 内部的字段查找逻辑仍会拒绝,不走继承链判断可访问性
为什么不能绕过访问限制?
AtomicIntegerFieldUpdater 底层依赖 Unsafe 的 compareAndSwapInt,而 Unsafe 操作字段前必须通过反射拿到 Field 对象。JDK 的反射机制对 private/protected 字段默认不允许直接访问,而 updater 并未调用 setAccessible(true) ——这是有意为之的设计选择,为了性能和安全性:避免每次操作都做访问检查或暴力反射。
- 它不模拟“编译器视角”的继承关系,只认字段在声明类中的实际修饰符
- 即使你手动 setAccessible,updater 也不会用;它的初始化过程会在构造时就校验并失败
可行的替代方案
若需原子更新非 public 字段,推荐以下方式:
立即学习“Java免费学习笔记(深入)”;
- 将字段改为
public volatile int(最直接,但破坏封装性,适合内部高性能场景) - 在字段所在类中提供 public 的原子更新方法(例如
incrementAndGet()),内部使用AtomicInteger成员或 synchronized + volatile,兼顾安全与封装 - 改用
AtomicInteger字段替代普通 int 字段,通过对象引用来操作,无需 updater
继承场景下的常见误区
有人尝试在子类中用 newUpdater(Child.class, "inheritedField"),期望借助继承访问父类 protected 字段。这行不通:updater 查找字段时只在指定 Class 的直接声明中搜索,不会向上查找父类字段;即使找到,字段修饰符仍是 protected,校验失败。
- updater 不支持跨类访问,也不支持字段继承解析
- 字段名必须精确匹配,且必须在传入的 Class 对象中声明(而非继承而来)


















