局部变量在函数调用时动态分配于栈帧中,首次赋值才写入值,未初始化则为未定义状态;基本类型存值,引用类型存堆地址;生命周期与栈帧绑定,函数结束即自动销毁。

局部变量在栈上初始化,不是“定义即分配”,而是“首次赋值才分配”。它不依赖系统默认值,也不占用固定内存位置,一切由函数调用时的栈帧动态决定。
栈空间按需划出,不是提前预留
函数被调用时,CPU通过esp(栈顶指针)和ebp(栈底指针)协作,在栈区划出一块专属空间——这就是该函数的栈帧。局部变量就“住”在这块刚划出来的区域里,但此时它们只是地址空位,还没有实际内容。
比如执行 int a = 10; 这一行时,编译器才生成指令:在栈帧内找一个4字节位置,把数值 10 写进去。没这一步赋值,a 就根本不存在于内存中——连零都不是,是未定义状态。
基本类型存值,引用类型存地址
局部变量的存储方式取决于类型:
- 基本类型(如
int、char、boolean):值直接写入栈帧对应位置 - 引用类型(如
String、ArrayList):栈上只存一个4或8字节的内存地址,真实对象在堆中,栈里这个地址指向它
注意:这个地址本身也要显式初始化,比如 String s = "hello"; 才让 s 在栈上有确定值;若只写 String s; 就未初始化,编译直接报错。
生命周期绑定栈帧,退出即消失
局部变量的生命完全依附于它的栈帧:
- 函数开始执行 → 栈帧创建 → 局部变量可被初始化
- 函数执行结束 → 栈帧弹出 → esp 回退,整个栈帧空间自动“作废”
- 没有垃圾回收参与,也不需要手动释放,纯粹靠栈机制自动管理
正因为如此,同一个函数多次调用,每次的局部变量都位于不同栈地址,互不影响。
和全局/静态变量有本质区别
全局变量或 static 局部变量在程序启动时就分配在 .data 或 .bss 段,有确定地址、默认初值(如 0 或 null),且全程存在。
而普通局部变量:
- 地址每次调用都可能不同
- 无默认值,必须显式初始化才能用
- 不占数据段,只活在栈帧这一小片临时空间里











