Java变量生命周期由声明位置、所属主体和存活时长决定:局部变量进块即生出块即亡,需显式初始化;实例变量随对象存续,有默认值;静态变量从类加载到JVM终止,全实例共享。

Java 变量的生命周期不是抽象概念,而是由它“在哪声明”“归谁所有”“存在多久”三个事实共同决定的。写错位置、用错修饰符、误判存活时间,都可能引发编译失败、空指针、内存泄漏或数据污染。
局部变量:进块即生,出块即亡
局部变量包括方法参数、方法体内定义的变量、以及 if、for、普通代码块 {} 中声明的变量。它们只活在栈帧里,生命周期极短且确定:
- 执行到声明语句时才分配内存,不声明就不存在;
- 作用域严格限制在最近的一对大括号内,超出即不可见;
- 每次进入块(比如 for 循环每轮)都会新建一份,互不影响;
- 必须显式初始化才能读取,
int x;后直接System.out.println(x);编译报错; - 不能加
public、static等修饰符,天然无访问控制。
成员变量(实例变量):跟着对象走
定义在类中、方法外,且没有 static 修饰的变量,属于对象状态的一部分,存于堆内存:
- 随
new操作一起诞生:对象创建时,所有成员变量同步分配内存并完成默认初始化(int → 0,Object → null); - 只要对象还被至少一个强引用持有,它就一直有效;
- 对象变为 GC 候选后,其所有成员变量一并释放,不单独回收;
- 若与局部变量同名,会被遮蔽,需用
this.xxx显式访问; - 避免长期持有大对象(如未清理的缓存、未注销的监听器),否则会拖慢对象回收,造成内存泄漏。
静态变量(类变量):从类加载活到 JVM 结束
用 static 修饰、定义在类中方法外的变量,属于类本身,存于方法区(JDK 8+ 是元空间):
立即学习“Java免费学习笔记(深入)”;
- 类首次被主动使用(如调用静态方法、访问非 final 静态字段、
new实例等)时触发类加载,随后完成初始化,且仅一次; - 所有实例共享同一份值,修改会影响全部对象;
- 生命周期与类绑定,正常运行期间几乎不会卸载——意味着你写的
public static Map<String, Object> cache会一直占着内存; - 慎用静态集合或静态回调,尤其不要持有
Activity、Context、View等易导致内存泄漏的对象; - 多线程并发修改时需同步,否则可能出现脏读、覆盖丢失等数据不一致问题。
别混淆“看不见”和“还活着”
作用域结束 ≠ 变量立即消失。比如局部变量出了 {} 就不能再访问,但它的栈空间还没被覆盖;成员变量所属对象即使被设为 null,只要 GC 还没运行,它仍驻留在堆中。真正决定“是否还活着”的,是可达性:JVM 通过根可达分析判断对象是否可回收,变量的生命依附于它所属的宿主(块、对象、类)。



















