1. 概述
- 数组值是相同类型的、用一个标识符名称封装到一起的一个对象序列或基本类型数据序列。
- 当创建一个数组对象时,实际上就是创建了一个引用数组,并且每个引用都会自动被初始化为一个特定值,该值拥有自己的关键字
null
。一旦 Java 看到null
,就知道这个引用还没有指向某个对象。在使用任何引用前,必须为其指定一个对象;如果试图使用一个还是null
的引用,在运行时将会报错。 - 还可以创建用来存放基本数据类型的数组。同样,编译器也能确保这种数组的初始化,因为它会将这种数组所占的内存全部置零。
- 当创建一个数组对象时,实际上就是创建了一个引用数组,并且每个引用都会自动被初始化为一个特定值,该值拥有自己的关键字
- 基本特点
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
- 数组长度是确定的。数组一旦被创建,它的大小就是不可以改变的
- 其中,每一个数据称作一个元素,每个元素可以通过一个索引来访问它们
- 数组(元素)类型可以是任何数据类型,包括 [基本类型] 和 [引用类型]
- 元素必须是相同类型,不允许出现混合类型
- 数组变量本身是引用类型,是个对象,数组中的每个元素相当于该对象的成员变量
- Java 中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中存储的
- 创建数组对象会在堆中开辟一整块连续的空间,而数组名引用的就是这块连续空间的首地址
2. 声明
- 数组是通过方括号下标操作符
[]
来定义和使用的 - 声明:
Type[] arrName;
,表明类型是"一个 Type 型数组" - 声明的时候并没有实例化任何对象,只有在实例化数组对象时,JVM 才分配空间,这时才与长度有关
- 现在拥有的只是对数组的一个引用(你已经为该引用分配了足够的存储空间),而且也没给数组对象本身分配任何空间
- 为了给数组创建相应的存储空间,必须写 {初始化表达式};定义并用运算符 new 为之分配空间后,才可以引用数组中的每个元素
3. 初始化
- 默认初始化
- 数组是引用类型,它的元素相当于类的成员变量,因此数组一经分配空间,其中的每个元素也被按照成员变量同样的方式被隐式初始化
- 大致来说就是将数组所占的那块内存空间全部置零
- 静态初始化
- 在声明数组的同时就为数组元素分配空间并赋值
- 格式(以 int 为例)
int[] arr1; ...; arr1 = new int[]{1, 2, 3};
// []里面什么都不用写!int[] arr2 = {1, 2, 3};
// 这种方式必须 {声明 + 初始化} 一起!
- 在创建完成后,其实会先默认初始化,然后再用提供的值进行覆盖
- 对于数组,初始化动作可以在代码的任何地方,但也可以使用一种特殊的初始化表达式(格式 2),它必须在创建数组的地方出现。这种特殊的表达式是由一对花扩号括起来的值组成的。在这种情况下,存储空间的分配(等价于使用 new)将由编译器负责
- 动态初始化:声明数组且为数组元素分配空间与赋值的操作分开进行
- 格式:
Type[] arrName; ...; arrName = new Type[length];
// 声明和初始化可以分开 - 此时,数组元素已被默认初始化;在之后可直接通过数组下标对元素进行赋值
- 格式:
4. 数组长度、遍历
- 所有数组(无论元素是对象还是基本类型)都有一个固定成员,可以通过它获知数组内包含了多少个元素,但不能对其修改。这个成员就是length,数组一旦初始化,其长度是不可变的。
- 数组元素的引用方式:
arrName[index]
,下标可以是整型常量或整型表达式;如a[3]
,b[i]
,c[6*i]
。 - Java 数组计数从第 0 个元素开始,所以能使用的最大下标数是 length-1。要是超过这个边界,就会出现运行时错误(即异常)。
- 我们可以通过下标来遍历数组中的元素,遍历时可以读取元素的值或者修改元素的值。
5. Exer
a. 生成无重复的随机数组
b. 数组元素反转
c. 冒泡排序
d. 小面试题
6. 多维数组
如果说可以把一维数组当成几何中的线性图形, 那么二维数组就相当于是一个表格。对于二维数组的理解,我们可以看成是一维数组 array1 又作为另一个一维数组 array2 的元素而存在。其实,从数组底层的运行机制来看,其实没有多维数组,多维数组可以看成以数组为元素的一维数组。
6.1 初始化
6.2 二维的初始化
- 外层元素:地址值;默认 null
- 内层元素:跟一维一样,就具体的数据;默认见《一维》
6.3 内存图解