static变量存放在方法区(Java 8+为元空间),与类结构信息共存,被所有实例共享且仅初始化一次。
static变量在JVM中存放在哪里
static变量属于类,不依赖实例,JVM把它存在方法区(Java 8+ 是元空间 Metaspace),和类的结构信息(如常量池、字段表、方法表)放在一起。它被所有实例共享,且只初始化一次——类首次主动使用时触发类初始化, 方法执行 static 变量赋值和 static 块。
注意:不是所有 static 变量都“立即”初始化。比如 final static 基本类型字面量(如 public static final int MAX = 100;)会在编译期直接内联,运行时甚至不进 ;而 public static final List NAMES = new ArrayList(); 就必须走初始化流程。
static方法为什么不能访问this和非static成员
因为 this 指向当前实例,而 static 方法在类加载后即可调用,此时可能根本没创建任何对象。JVM 调用 static 方法时,不会压入对象引用到操作数栈顶部,也就没有隐式 this 参数——这和实例方法签名本质不同:实例方法实际签名为 (LMyClass; I)V(第一个参数是 this),而 static 方法是 (I)V。
常见错误现象:
立即学习“Java免费学习笔记(深入)”;
- 在 static 方法里写
this.field→ 编译报错non-static variable cannot be referenced from a static context - 调用
instanceMethod()不加对象前缀 → 同样编译失败 - 误以为
static synchronized锁的是“当前类实例” → 实际锁的是MyClass.class对象
static代码块与类加载时机的关系
static 代码块(static { ... })只在类初始化阶段执行一次,且按源码顺序合并进 方法。它不等于“类加载”,而是“类初始化”——类加载(Loading)可能早于初始化(Initialization),中间还隔着链接(Linking)阶段。
触发类初始化的典型场景: