Java数组

数组是一个连续的内存空间,在数组中可以存储多个相同类型的数据,数组的大小在初始化后不可改变。注意,这里的相同类型可以是类型声明的子类,因为子类是一种特殊的父类,比如可以声明一个水果数组,这个数组里可以存储香蕉和苹果,因为香蕉和苹果是继承自水果。

1. 声明

Java支持两种语法来定义一个数组

type[] arrayName ;
type arrayName [];
// 在声明数组是不可以在"[]"中加上长度,type arrayName [5]

在Java中其实可以将"type[]"看做一个整体,这就是一种数据类型,类似于int,boolean...arrayName是这个类型的一个变量实例,所以尽量不使用第二种声明方式。

2. 初始化

2.1 静态初始化

在数组创建阶段就已经确定了初值和数组的长度,编译器会根据{}里的内容确定数组长度

int[] intArray = {1, 2, 3, 4, 5, 6} ;
// 或者
int[] intArray = new int[]{1, 2, 3, 4, 5, 6} ;

用第二种方法时,数组变量也可以先声明再初始化

int[] intArray ;
intArray = new int[]{1, 2, 3, 4, 5, 6} ;

2.2 动态初始化

动态初始化只确定数组的长度,数组里的内容使用一个默认值

int length = 5 ;
int[] intArray = new int[length] ; 

对于基本数据类型和引用类型,默认值如下

图片说明

3. 遍历

使用方括号[]和下标来访问数组里的员,结合循环体可以遍历一个数组,其中数组的长度存储在数组类型的一个成员length中,和C/C++一样,数组的下标从0开始,最大下标为length-1

int[] array = {1, 2, 3, 4, 5, 6} ;
for(int i = 0; i < array.length; i++){
    Systemp.out.println(array[i]) ;
}
// 在Java中还可以使用foreach语句来遍历数组
foreach(int temp : array){
    System.out.println(temp) ;
    // 注意修改temp不会影响array中的数据
}

4. 对象模型

Java中的数组对象,和数组类型变量其实是一个数组两个部分。数组类型变量其实就是一个被严格限制的指针变量称为引用,这个变量被创建在栈上,它指向创建在堆上的实际数组对象,是数组对象的一个引用。一个数组对象可以用多个引用,如果没用引用那么将会被jvm回收掉。那么类似的,一个引用变量不一定非要指向初始化后的数组,也可以指向其他数组

int[] a1 = {1, 2, 3, 4, 5, 6} ;
int[] a2 = {4, 7 ,9, 0} ;
int[] a3 = a1 ;
a2 = a1 ;
// 如果只使用等号对引用类型变量赋值,只是改变了指向的对象,并不会再在内存中创建一个数组
// 因此a1, a2, a3其实都指向同一个{1, 2, 3, 4, 5, 6},而不存在3个数组对象

如果是一个引用类型的数组,那么要注意数组的每一个变量都是一个引用

String[] s = new String[2] ;
s0 = "Hello" ;
s1 = "World" ;
s[0] = s0 ;
s[2] = s1 ;
// s是一个引用,s指向一个数组,数组的每一个变量都是一个引用
// s0 是一个引用,指向“Hello”这个数据对象
// s[0] 是一个引用,指向“Hello”这个数据对象
// s0和s[0]指向同一个数据对象

如下图所示

图片说明

5. 多维数组

Java中并不存在直接定义的多维数组,也就是说并不能用一块连续的存储空间表示一个二维数组。

但是我们知道一维数组变量本质上是一个指针,指向一个一维数组对象。那么可以定义一个一维数组,这个数组的每个成员都指向一个一维数组,就模拟了二维数组。

int[][] b ;
// int[]是一个整体,表示一维数组类型
// int[]后接[]表示一个数组,其成员的类型为:int[]
b = new int[3][4]
// 定义一个3行四列的数组

// 不全部初始化
int[][] c = new int[3][] ;
// c只定义了一个含有3个成员的引用数组,值为null

b的内存模型如下

图片说明

6. Array类

Array类是Java中处理数组的一个工具类,其中包括了许多的静态成员函数可以直接操作数组。

  • int binarySearch(type[] a, type key),要求数组升序排列,如果搜索失败返回负数

  • int binarySearch(type[] a, int from, int to, type key)

  • type[] copyOf(type[] original, int length),复制数组,如果original数组长度小于length,则新数组后面填默认值

  • type[] copyOf(type[] original, int from, int to)

  • boolean equals(type[] a1, type[] a2),如果数组a1和a2长度相等,而且每个元素也相等,返回true

  • void fill(type[] a, type val),给a的所有元素赋值val

  • void fill(type[] a, int from, int to, type val)

  • void sort(type[] a),从小到大排序

  • void sort(type[] a, int from, int to)

  • String toString(type[] a),将数组元素转化为字符串,然后连接起来