Java数组是堆上固定长度的引用类型对象,下标从0开始,有length字段无size()方法,静态与动态初始化不可混用,越界访问抛ArrayIndexOutOfBoundsException。

Java里的数组就是一块连续内存里塞满同类型数据的固定容器,下标从0开始,长度创建后就锁死——它不是语法糖,是实实在在的引用类型对象。
数组本质是堆上的对象,不是基本类型
很多人以为 int[] 是“int的数组”,其实它是“指向一个 int[] 类型对象的引用”。这个对象在堆上分配,哪怕元素是 int 这种基本类型,整个数组本身仍是引用类型。这意味着:
-
int[] a = new int[3]; int[] b = a;→ 修改b[0]会同步影响a[0] - 未初始化就用(比如声明了
String[] arr;没new就直接arr[0] = "x")会抛NullPointerException - 数组有
.length字段,但没有.size()方法——因为它是对象,不是集合
静态初始化和动态初始化不能混用
这是新手高频翻车点:你不能一边指定长度,一边又给具体值。
- ✅ 正确:
int[] a = new int[]{1, 2, 3};(静态,长度由元素数决定) - ✅ 正确:
int[] b = new int[5];(动态,所有元素自动为0) - ❌ 错误:
int[] c = new int[3]{1, 2, 3};→ 编译不通过 - ⚠️ 注意:
int[] d = {1, 2, 3};这种简写只能出现在声明语句中,不能拆成两行写
访问越界不是警告,是立刻崩溃
ArrayIndexOutOfBoundsException 不是编译错误,而是在运行时一碰就炸的异常。常见触发场景:
立即学习“Java免费学习笔记(深入)”;
- 循环条件写成
i 而不是i - 对空数组(
arr.length == 0)还去读arr[0] - 用负数下标,比如
arr[-1] - 二维数组里只检查了
i ,却忘了j
安全做法永远是先校验:if (idx >= 0 && idx
数组长度不可变,扩容必须手动搬数据或换结构
arr.length 是 final 字段,不能赋值;想“加元素”?没这回事。两种现实路径:
- 自己用
Arrays.copyOf()创建新数组并复制:arr = Arrays.copyOf(arr, arr.length + 1); - 直接改用
ArrayList—— 它底层也是数组,但封装了扩容逻辑(1.5倍增长),且支持add()、remove() - 注意:
int[]无法直接转成ArrayList,得用Arrays.stream(arr).boxed().collect(Collectors.toList())
真正需要频繁增删的场景,硬扛原生数组只会让代码越来越脆弱。









