上一篇
Java数组如何分配内存?
- 后端开发
- 2025-06-09
- 4457
在Java中,可以通过两种方式为数组开辟空间:,1. **静态初始化**:声明时直接赋值,如
int[] arr = {1,2,3};
自动分配空间。,2. **动态初始化**:使用
new
关键字指定长度,如
int[] arr = new int[5];
开辟5个整型空间,数组长度固定不可变。
数组开辟空间的两种方式
静态初始化(声明时直接赋值)
特点:在声明数组的同时指定元素值,编译器自动计算长度并分配空间。
语法:
数据类型[] 数组名 = {元素1, 元素2, ..., 元素n}; // 或 数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, ..., 元素n};
示例:
// 方式1:直接赋值 int[] arr1 = {10, 20, 30}; // 自动分配3个int空间(12字节) // 方式2:new语法赋值 String[] arr2 = new String[]{"Java", "Python", "C++"}; // 分配3个String引用空间
动态初始化(声明时指定长度)
特点:先指定数组长度,再通过索引赋值,未显式赋值时,元素取默认值(如int为0,对象为null)。
语法:
数据类型[] 数组名 = new 数据类型[长度];
示例:
double[] arr3 = new double[5]; // 分配5个double空间(40字节) arr3[0] = 3.14; // 索引赋值 // 对象数组示例 Person[] persons = new Person[3]; // 分配3个Person引用空间(初始值为null) persons[0] = new Person("Alice"); // 实例化后赋值
内存分配原理(栈与堆)
- 栈内存(Stack)
- 存储数组引用变量(如
arr1
、arr2
),固定占用4字节(32位JVM)或8字节(64位JVM)。
- 存储数组引用变量(如
- 堆内存(Heap)
- 实际数组对象存储在堆中,空间大小 = 数组头(12字节) + 元素数量 × 元素类型大小。
int[10]
占 12(数组头) + 10×4(int大小) = 52字节 → JVM对齐为56字节。
内存示意图:
栈内存 堆内存
┌────────┐ ┌─────────────────┐
│ arr1 │───→ │ int[3] │
│ (引用) │ ├─────────────────┤
└────────┘ │ 0: 10 │
│ 1: 20 │
│ 2: 30 │
└─────────────────┘
关键注意事项
- 长度不可变
数组一旦创建,长度固定,扩容需用新数组复制(如Arrays.copyOf()
)。 - 索引从0开始
访问范围:0
到长度-1
,越界会抛出ArrayIndexOutOfBoundsException
。int[] arr = new int[3]; arr[3] = 100; // 错误!最大索引为2
- 默认值规则
- 基本类型:
int
/double
默认为0
,boolean
为false
。 - 引用类型:默认为
null
(未指向实际对象)。
- 基本类型:
多维数组的空间开辟
多维数组本质是“数组的数组”,需逐层分配空间:
// 静态初始化 int[][] matrix1 = {{1, 2}, {3, 4}}; // 动态初始化 int[][] matrix2 = new int[2][3]; // 直接分配2×3空间 int[][] matrix3 = new int[2][]; // 仅分配第一维 matrix3[0] = new int[]{1, 2}; // 第二维手动分配 matrix3[1] = new int[4]; // 第二维长度可不同
- 静态初始化:适合已知具体元素的场景,代码简洁。
- 动态初始化:适合长度已知、元素后续赋值的场景。
- 底层逻辑:引用变量存于栈,数组对象存于堆,长度不可变,索引严格校验。
引用说明: 参考Oracle官方文档 Java Arrays Tutorial 及《Java核心技术卷I》(第11版),确保内容权威性,内存模型部分依据JVM规范(Java SE 17)描述。