静态变量实现跨对象数据共享,本质是让变量归属类本身而非实例,所有对象操作同一内存地址;声明需在类体内部、加static修饰符、不在方法中;推荐private static+public static封装访问;多线程下须用AtomicInteger等原子类或Class锁保障安全。

静态变量实现跨对象数据共享,本质是让变量归属类本身,而非某个实例——所有对象操作的是同一块内存地址,改一处,全部可见。
声明位置和访问权限要规范
必须满足三个条件:写在类体内部、加 static 修饰符、不在任何方法或代码块中定义。推荐组合是 private static 声明 + public static 访问方法:
- 用
private static AtomicInteger counter = new AtomicInteger(0);替代public static int count = 0;,避免外部随意赋值和丢失校验能力 - 提供
public static int increment() { return counter.incrementAndGet(); }这样的封装方法,后续可加日志、限流或权限控制 - 构造器里调用该方法,对象一创建就自动计入,无需业务层重复操作
跨对象读写行为很直接
所有实例(包括 new 出来的、反射创建的、甚至尚未实例化但类已加载的上下文)都指向同一个变量地址:
- 基本类型(如 int、boolean)共享的是值本身;引用类型(如 List、Map)共享的是对象地址——多个对象操作的是同一个集合
- 通过类名访问最清晰:
Stats.totalRequests.incrementAndGet();用实例调用(如obj.counter)语法合法,但语义模糊,容易误以为是实例行为 - 若某处执行
logs = new ArrayList<>();,只是把静态引用指向新对象,原列表仍存在,其他地方持有的旧引用不受影响
多线程下必须保障线程安全
静态变量天然跨线程可见,但不等于线程安全。复合操作(如 count++、list.add(x))不是原子的,高并发时必然丢值:
立即学习“Java免费学习笔记(深入)”;
- 计数类场景首选
AtomicInteger或AtomicLong,底层用 CAS,无锁高效 - 逻辑复杂需同步时,锁对象用
MyClass.class,不要用this(实例锁无效)或new Object()(锁对象不唯一) -
volatile只保可见性,不保原子性,不能替代原子类
跨类使用简单但有边界
只要类能被正确 import,就能通过类名直接访问静态成员,不依赖 Spring 或任何框架:
- 建一个专用类(如
AppStats或Config),集中管理共享变量 - 其他类(如
OrderService)直接调用AppStats.activeUsers.incrementAndGet() - 注意隐形边界:不同类加载器加载的同名类(如 DevTools 热部署、OSGi 场景),其静态变量完全隔离,互不可见


















