Java数组变量存于栈中仅保存堆地址,真实数据(含length头部与元素)连续存储于堆;静态初始化本质仍是堆分配,并非栈上存储。

数组变量在栈,真实数据在堆
声明一个数组,比如 int[] arr = new int[5];,JVM 做了两件事:在栈上分配一个 4 字节(32 位 JVM)或 8 字节(64 位 JVM)的引用变量 arr,同时在堆上开辟一块连续内存,存放 5 个 int 值(每个占 4 字节,共 20 字节,不含对象头等开销)。arr 本身不存数字,只存那个堆地址——就像一张纸条写着“第3排第2号储物柜”,纸条在桌上(栈),东西真正在柜子里(堆)。
赋值不等于拷贝,只是复制地址
写 int[] b = arr; 并没创建新数组。栈里多了一个叫 b 的纸条,但它写的还是同一个柜子编号。改 b[0] = 99,arr[0] 立刻变成 99。这不是 bug,是设计使然——Java 所有引用类型赋值都这样,包括数组、String、自定义对象。
- 真正想隔离修改?必须新开堆空间
- 基本类型数组用 Arrays.copyOf(arr, arr.length) 或 System.arraycopy()
- 对象数组还需判断:浅拷贝(新数组+原对象引用)还是深拷贝(新数组+新对象实例)
连续内存带来的性能双面性
堆里那块连续空间让随机访问飞快:要取 arr[3],JVM 直接算 首地址 + 3 × 4,一步到位,O(1) 时间。但代价是增删困难:在中间插入一个元素,后面所有数都得往后挪一位,最坏 O(n)。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 频繁插入/删除?考虑 ArrayList(内部也是数组,但封装了扩容逻辑)或 LinkedList
- 大量只读遍历?数组仍是最快选择,无方法调用开销,CPU 缓存友好
- 大数组(如千万级)初始化时,JVM 可能触发 TLAB 分配或直接走老年代,影响 GC 行为
初始化值不是“空”,而是确定的默认值
new int[5] 创建后,5 个位置立刻被填满 0;new boolean[3] 全是 false;new String[2] 则是两个 null。这些默认值写入发生在堆内存分配之后、构造完成之前,是 JVM 强制保证的行为,不是“没初始化”。
立即学习“Java免费学习笔记(深入)”;
- 基本类型默认值固定(int→0,double→0.0,boolean→false)
- 引用类型默认值统一为 null,不会自动 new 出实例
- 静态初始化(如 int[] a = {1,2,3};)本质仍是堆分配+逐个赋值,只是语法糖

















