Java数组长度不可变是JVM堆内存布局与设计逻辑决定的硬性事实:其在堆中占据固定连续空间,length为final字段定义数组固有大小,扩容实为创建新数组,此举保障O(1)访问、JIT优化及GC精准回收。

Java数组长度不可变,不是语法限制的表面现象,而是堆内存布局和JVM设计逻辑共同决定的硬性事实。
它在堆里“占了一块固定地盘”
当你写 int[] arr = new int[5];,JVM就在堆中划出一块连续、精确为20字节(5 × 4)的区域,并记录下起始地址。后续所有 arr[i] 访问,都靠这个公式算地址:起始地址 + i × 4。如果允许中途加长,就得搬走整块数据、申请更大连续空间、再复制——这已超出数组本职,是 ArrayList 的事。
length 不是属性,是“身份铭牌”
-
arr.length是final字段,编译期就锁死,连反射强行改都会失败或被JVM拦截; - 它不描述“当前用了多少”,而定义“这个数组对象生来就是多大”;
- 哪怕你把全部元素设为
null或0,这块内存和它的长度值仍原封不动。
你以为的“变长”,其实是“换人”
写下 arr = new int[10]; 并没拉长原数组,只是让变量 arr 这个标签从旧地址撕下来,贴到另一块新分配的10元素内存上。原来的5元素数组若无其他引用,就等着被GC回收——两个数组彼此独立,互不影响。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
为什么非得这么设计?
- O(1)访问必须依赖定长偏移计算,动态长度会让下标寻址变成查表或条件跳转;
- JIT编译器靠length恒定做优化,比如去掉循环边界检查、自动展开小循环;
- GC需要明确对象边界,连续定长结构让垃圾回收器能精准识别哪些字节属于这个数组。
不复杂但容易忽略:数组的不可变性,是内存、性能、安全三者妥协后最稳的落点。需要弹性?交给集合类去处理,别强求数组做它不该做的事。
立即学习“Java免费学习笔记(深入)”;

















