静态变量存于方法区(JDK 8+元空间),类加载时初始化且全局唯一;非静态变量存于堆,每次new独立分配。静态变量通过类名访问,非静态必须通过实例访问,静态方法中不可直接访问非静态成员。
静态变量和非静态变量的内存位置不同
静态变量(static 修饰)存在方法区(JDK 8+ 是元空间),类加载时初始化,整个 JVM 生命周期内只有一份;非静态变量(实例变量)存在堆中,每次 new 对象时才分配,每个对象独有一份。
这意味着:修改一个对象的非静态变量,不影响其他对象;但修改静态变量,所有对象看到的都是同一个值——哪怕它们属于不同类实例,甚至来自不同线程(除非加同步)。
访问方式差异直接暴露设计意图
静态变量可通过类名直接访问:MyClass.count;非静态变量必须通过实例访问:obj.name。编译器会严格检查:在静态方法(如 main)里直接引用 this.name 或未加实例前缀的 name,会报错 non-static variable cannot be referenced from a static context。
常见误操作:
立即学习“Java免费学习笔记(深入)”;
- 在
@Test方法(默认静态)里试图调用非静态字段或方法,忘了加new MyClass() - 把工具类中的配置项(如
DEFAULT_TIMEOUT)误声明为非静态,导致每次 new 都重复加载 - 把本该共享的缓存(如
Map)声明为非静态,内存占用翻倍且无法跨实例复用
初始化时机和顺序影响程序行为
静态变量在类第一次主动使用时触发类初始化,按代码顺序执行静态块和静态变量赋值;非静态变量在构造器执行前、按声明顺序初始化,再进入构造器体。