基本数据类型变量是否存于栈中取决于声明位置:仅局部变量(方法、代码块或循环内声明)的值直接存入栈帧;成员变量随对象存堆,静态变量存方法区,数组元素也存堆。

基本数据类型变量在栈中存储,关键不是“类型本身”,而是“它在哪声明”。只有局部变量才真正在栈帧里存值;其他位置的同类型变量,可能在堆或方法区。
局部变量:值直接写进栈帧
在方法、代码块或循环里声明的基本类型(比如 int count = 42;、char c = 'A';),JVM 会在当前线程的栈帧中分配一块固定大小的连续空间,把数值的二进制表示原样写进去:
- int 占 4 字节 → 存 42 的补码 0x0000002A
- double 占 8 字节 → 存 IEEE 754 双精度格式
- boolean 虽语义简单,但 JVM 通常按 1 字节处理(实现细节,不跨平台保证)
方法执行结束,整个栈帧弹出,这些值立刻消失,不触发垃圾回收。
赋值就是复制值,不是共享或引用
栈中存的是数值本身,不是地址。所以:
立即学习“Java免费学习笔记(深入)”;
- int a = 100; 和 int b = a; → 把 a 对应的 4 字节完整拷贝给 b,a 和 b 完全独立
- 修改 b 不会影响 a,因为它们是两份相同的二进制数据
- 哪怕写 int x = 5; 和 int y = 5;,x 和 y 也各自占栈空间,值相同 ≠ 地址相同
这和 Integer 缓存(-128~127)无关——那是堆上对象复用,和栈里的基本类型毫无关系。
别误以为“所有基本类型都在栈里”
常见误解来源是忽略了声明位置:
- 成员变量(如 private int id;)→ 随所属对象一起存在堆中,是对象实例数据的一部分
- 数组元素(如 int[] arr = new int[3];)→ 整个数组是对象,3 个 int 值都存在堆中,栈里只存 arr 这个引用
- 静态变量(如 public static final int VERSION = 1;)→ 属于类信息,存在方法区(元空间)
所以,“int 一定在栈里”是错的;真正决定位置的是变量的作用域和生命周期。
栈里没有缓存、没有池、没有共享机制
栈内存模型极简:分配 → 使用 → 弹出。它不维护任何值的复用逻辑:
- 编译期常量(如 final int MAX = 100;)可能被内联优化,但运行时栈中仍为独立槽位
- 没有类似字符串常量池那样的共享设计
- 不会因为两个变量值相同,就让它们指向同一块栈内存
理解这一点,才能区分清楚“栈中值拷贝”和“堆中对象共享”的行为差异。


















