静态变量通过归属类而非实例实现跨对象数据共享,适用于计数、配置等场景;需private static声明并配public static方法,用atomicinteger保障线程安全,避免内存泄漏与测试污染。

静态变量实现跨对象共享数据,本质是让变量归属类本身而非实例,所有对象操作同一内存地址。它不是“万能全局变量”,但对计数、配置、轻量状态等场景非常直接有效。
明确声明位置和访问权限
静态变量必须定义在类体内部、方法外部;加 static 修饰符;推荐用 private static 声明,再提供 public static 的读写方法:
- 避免直接暴露
public static int count—— 失去控制,无法加校验或日志 - 构造器中调用自增逻辑(如
counter.incrementAndGet()),对象一创建就自动计入 - 跨类访问时,直接用
ClassName.methodName()或ClassName.field,无需实例
保证线程安全是关键前提
普通 count++ 是非原子操作,多线程下必然丢值。不能靠“好像没出问题”来判断:
- 高并发场景首选
private static AtomicInteger counter = new AtomicInteger(0),调用incrementAndGet() - 逻辑复杂需同步时,在 setter 或关键方法内用
synchronized (Counter.class) { ... } - 不要用
volatile代替原子类——它只保可见性,不保原子性
跨类使用要简洁且可控
不需要 Spring、不需要注入、不依赖任何框架,纯 Java 原生能力即可:
- 建一个专用类(如
Stats或AppConfig),集中管理共享变量 - 其他业务类(如
OrderService、UserService)直接调用Stats.totalRequests.incrementAndGet() - 注意:不同类加载器加载的同名类,其静态变量互不相通(微服务或热部署场景需留意)
避开常见陷阱才真正落地
看似简单,但错一步就引发隐性故障:
- 别存 Context、Activity、大缓存 Map 等对象引用——静态持有导致内存泄漏
- 单元测试间会残留状态,建议在
@AfterEach中重置计数器(如Stats.reset()) - 静态代码块里初始化要谨慎,若依赖未就绪的配置,会抛
ExceptionInInitializerError - 需要多租户隔离、上下文绑定或依赖注入时,该上单例 Bean 就别硬扛 static











