本文已参与「新人创作礼」活动,一起开启掘金创作之路。
3. 数组
3.1 数组的概述
1. 定义
数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
2. 数组的常用概念
- 数组名
- 下标(或索引)
- 元素
- 数组的长度:元素的个数
3. 特点
- 数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。
- 创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址。
- 数组的长度一旦确定,就不能修改。
- 我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。
- 数组是有序排列的
4. 分类
- 按照维度
- 一维数组
- 二维数组
- 三维数组
- …
- 按照元素的数据类型分
- 基本数据类型元素的数组
- 引用数据类型元素的数组(即对象数组)
3.2 一维数组的使用
1. 声明方式
type var[] 或 type[] var
例如:
int a[];int[] a;String a[];String[] a;
2. 初始化
-
静态初始化:在定义数组的同时就为数组元素分配空间并赋值。
int arr[] = new int[]{ 3, 9, 8}; // ----------------------------- int[] arr = {3,9,8}; // ----------------------------- String names[] = { “李四光”,“茅以升”,“华罗庚” } -
动态初始化:数组声明且为数组元素分配空间与赋值的操作分开进行。
int[] arr = new int[3]; arr[0] = 3; arr[1] = 9; arr[2] = 8; // ----------------------------- String names[]; names = new String[3]; names[0] = “钱学森”; names[1] = “邓稼先”; names[2] = “袁隆平”;
注:数组一旦初始化完成,其长度就确定了。
3. 数组元素的引用
- 定义并用运算符new为之分配空间后,才可以引用数组中的每个元素
- 数组元素的引用方式:数组名[数组元素下标]
- 数组元素下标可以是整型常量或整型表达式。如a[3] , b[i] , c[6*i];
- 数组元素下标从0开始;长度为n的数组合法下标取值范围: 0 —>n-1;如int a[]=new int[3]; 可引用的数组元素为a[0]、a[1]、a[2]
- 每个数组都有一个属性length指明它的长度,例如:a.length 指明数组a的长度(元素个数)
4. 数组元素的默认初始化值
| 数组元素类型 | 元素默认初始值 |
|---|---|
| byte | 0 |
| short | 0 |
| int | 0 |
| long | 0L |
| float | 0.0F |
| double | 0.0 |
| char | 0或\u0000(表现为空),不是'0' |
| boolean | false |
| 引用数据类型 | null |
5. 内存简化结构
- 栈(stack):放局部变量
- 堆(heap):放new出来的结构,例如数组、对象等
6. 一维数组的内存解析
静态初始化
分析:(根据右上角代码)
- 根据new的数组长度在堆中开辟一块连续的空间,即1的内容
- 将变量arr放到栈中并让其指向堆中的连续空间的首地址,即2的内容
- 对连续空间中的值根据类型进行初始化,即3的内容
- 根据静态初始化的值对其进行覆盖,即4的内容
- 如果有其他的赋值操作,则进行相应的覆盖,即5的内容
其中1,2,3,4步对应代码int[] arr = new int[]{1, 2, 3},第5步对应arr[1] = 4
动态初始化
分析:(根据右上角代码)
- 根据new的数组长度在堆中开辟一块连续的空间,即1的内容
- 将变量arr放到栈中并让其指向堆中的连续空间的首地址,即2的内容
- 对连续空间中的值根据类型进行初始化,即3的内容
- 根据动态初始化的值对其进行覆盖,即4的内容
- 根据new的数组长度在堆中重新开辟一块连续的空间,即5的内容
- 让变量arr指向新开辟的空间的首地址,即6的内容
- 对重新开辟的空间进行初始化,即7的内容
- 第一次开辟的空间没有变量指向它了,则会在某一时刻被垃圾回收机制进行回收
其中1,2,3步对应代码int[] arr = new int[3],第4步对应arr[1] = 4,第5,6,7步对应arr = new int[3]
3.3 多维数组的使用
对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。其实,从数组底层的运行机制来看,其实没有多维数组。
1. 声明与初始化
| 二维数组:int[][] arr = new int[3][2] |
|---|
| 格式1(动态初始化):int[][] arr = new int[3][2]; |
|---|
| 定义了名称为arr的二维数组 二维数组中有3个一维数组 每一个一维数组中有2个元素 一维数组的名称分别为arr[0], arr[1], arr[2] 给第一个一维数组1脚标位赋值为78写法是:arr[0][1] = 78; |
| 格式2(动态初始化):int[][] arr = new int[3][]; |
|---|
| 二维数组中有3个一维数组 每个一维数组都是默认初始化值null (注意:区别于格式1) 可以对这个三个一维数组分别进行初始化:arr[0] = new int[3]; arr[1] = new int[1]; arr[2] = new int[2]; |
| 格式3(静态初始化):int[][] arr = new int[][]{{3,8,2},{2,7},{9,0,1,6}}; |
|---|
| 定义一个名称为arr的二维数组,二维数组中有三个一维数组 每一个一维数组中具体元素也都已初始化 第一个一维数组 arr[0] = {3,8,2}; 第二个一维数组 arr[1] = {2,7}; 第三个一维数组 arr[2] = {9,0,1,6}; 第三个一维数组的长度表示方式:arr[2].length; |
2. 默认值
规定:二维数组分为外层数组的元素,内层数组的元素
例如:int[][] arr = new int[3][2]的外层元素为arr[0],arr[1]等;内层元素为arr[0][0],arr[1][1]等
-
格式一
外层元素的初始化值为:地址值
内层元素的初始化值为:与一维数组初始化情况相同
-
格式二
外层元素的初始化值为:null
内层元素的初始化值为:不能调用,否则报错
3. 内存解析
分析:(根据右上角代码)
- 根据new的数组长度在堆中开辟一块连续的空间,即1的内容
- 将变量arr放到栈中并让其指向堆中的连续空间的首地址,即2的内容
- 对连续空间中的值根据类型进行初始化,即3的内容
- 再次根据new的数组长度在堆中开辟一块连续的空间,即4的内容
- 找到第一次开辟的空间的第二个位置将其内容赋值为新开辟的数组的首地址,即5的内容
- 对新开辟的连续空间中的值根据类型进行初始化,即6的内容
- 根据初始化的值对其进行覆盖,即7的内容
- 再次根据new的数组长度在堆中开辟一块连续的空间,即8的内容
- 找到第一次开辟的空间的第三个位置将其内容赋值为新开辟的数组的首地址,即9的内容
- 对新开辟的连续空间中的值根据类型进行初始化,即10的内容
其中1,2,3步对应代码int[][] arr = new int[3][],4,5,6,7步对应arr[1] = new int[]{1, 2},8,9,10步对应arr[2] = new int[3]