1. 数组的概述
1.1 概念
概念:是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
简称:多个数据的组合
数组中的概念
- 数组名
- 下标(或索引)
- 元素
- 数组的长度
数组的特点:
- 数组本身是
引用数据类型
,而数组中的元素可以是任何数据类型
,包括基本数据类型和引用数据类型。 - 创建数组对象会在内存中开辟一整块
连续的空间
。占据的空间的大小,取决于数组的长度和数组中元素的类型。 - 数组中的元素在内存中是依次紧密排列的,有序的。
- 数组,一旦初始化完成,其长度就是确定的。数组的
长度一旦确定,就不能修改
。 - 我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。
- 数组名中引用的是这块连续空间的首地址。
1.2 数组的分类
1、按照元素类型分:
- 基本数据类型元素的数组:每个元素位置存储基本数据类型的值
- 引用数据类型元素的数组:每个元素位置存储对象(本质是存储对象的首地址)(在面向对象部分讲解)
2、按照维度分:
- 一维数组:存储一组数据
- 二维数组:存储多组数据,相当于二维表,一行代表一组数据,只是这里的二维表每一行长度不要求一样。
2. 数组的使用
一维数组的使用:
- 数组的声明和初始化
- 调用数组的指定元素
- 数组的属性:length,表示数组的长度
- 数组的遍历
- 数组元素的默认初始化值
- 一维数组的内存解析(难)
2.1 一维数组的声明
格式:
代码语言:javascript复制//推荐
元素的数据类型[] 一维数组的名称;
//不推荐
元素的数据类型 一维数组名[];
数组的声明,需要明确:
(1)数组的维度:在 Java 中数组的符号是[],[]表示一维,[][**]表示二维。**
(2)数组的元素类型:即创建的数组容器可以存储什么数据类型的数据。元素的类型可以是任意的 Java 的数据类型。例如:int、String、Student 等。
(3)数组名:就是代表某个数组的标识符,数组名其实也是变量名,按照变量的命名规范来命名。数组名是个引用数据类型的变量,因为它代表一组数据。
2.2 一维数组的初始化
静态初始化 :
如果数组变量的初始化和数组元素的赋值操作同时进行,那就称为静态初始化。
静态初始化,本质是用静态数据(编译时已知)为数组初始化。此时数组的长度由静态数据的个数决定。
代码语言:javascript复制数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,...};
或
数据类型[] 数组名;
数组名 = new 数据类型[]{元素1,元素2,元素3,...};
动态初始化:
数组变量的初始化和数组元素的赋值操作分开进行,即为动态初始化。
动态初始化中,只确定了元素的个数(即数组的长度),而元素值此时只是默认值,还并未真正赋自己期望的值。真正期望的数据需要后续单独一个一个赋值。
代码语言:javascript复制数组存储的元素的数据类型[] 数组名字 = new 数组存储的元素的数据类型[长度];
或
数组存储的数据类型[] 数组名字;
数组名字 = new 数组存储的数据类型[长度];
2.3 数组元素的默认值
3. 一维数组内存分析
为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
java 虚拟机架构图:
区域名称 | 作用 |
---|---|
虚拟机栈 | 用于存储正在执行的每个 Java 方法的局部变量表等。局部变量表存放了编译期可知长度 的各种基本数据类型、对象引用,方法执行完,自动释放。 |
堆内存 | 存储对象(包括数组对象),new 来创建的,都存储在堆内存。 |
方法区 | 存储已被虚拟机加载的类信息、常量、(静态变量)、即时编译器编译后的代码等数据。 |
本地方法栈 | 当程序中调用了 native 的本地方法时,本地方法执行期间的内存区域 |
程序计数器 | 程序计数器是 CPU 中的寄存器,它包含每一个线程下一条要执行的指令的地址 |
3.1 一维数组在内存中的存储
与目前数组相关的内存结构: 比如:int[] arr = new int[]{1,2,3};
- 虚拟机栈:用于存放方法中声明的变量。比如:arr
- 堆:用于存放数组的实体(即数组中的所有元素)。比如:1,2,3
一个一维数组内存图:
代码语言:javascript复制public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr);//[I@5f150435
}
数组下标为什么是 0 开始的 :
- 因为第一个元素距离数组首地址间隔 0 个单元格
两个一维数组内存图:
两个数组独立
代码语言:javascript复制public static void main(String[] args) {
int[] arr = new int[3];
int[] arr2 = new int[2];
System.out.println(arr);
System.out.println(arr2);
}
两个变量指向一个一维数组
两个数组变量本质上代表同一个数组。
代码语言:javascript复制public static void main(String[] args) {
// 定义数组,存储3个元素
int[] arr = new int[3];
//数组索引进行赋值
arr[0] = 5;
arr[1] = 6;
arr[2] = 7;
//输出3个索引上的元素值
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
//定义数组变量arr2,将arr的地址赋值给arr2
int[] arr2 = arr;
arr2[1] = 9;
System.out.println(arr[1]);
}
4. 数组的常用算法
- 数值型数组的特征值的计算:最大值、最小值、总和、平均值等
- 数组元素的赋值。比如:杨辉三角;彩票随机生成数(6 位;1-30;不能重复);回形数
- 数组的复制、赋值
- 数组的反转
- 数组的扩容、缩容
- 数组的查找
- 线性查找
- 二分法查找(前提:数组有序)
- 数组的排序
- 冒泡排序:最简单
- 快速排序:最常用
5. Arrays 工具类的使用
熟悉一下内部的常用的方法
- toString() / sort() / binarySearch()
5. 数组中常见的异常
- ArrayIndexOutOfBoundsException
- NullPointerException