数组
定义多个同类型的变量
使用:
-
声明数组(引用类型):
数据类型[] 数组名;
数组名:记录的是数组的地址信息
数组类型:其实是数组里存储元素的类型
数组是一种引用类型,类型为数组
注意:
-
方括号中不能有任何内容
-
数组未完成初始化,无法通过编译
int[] arr; System.out.println(arr); //Exception in thread "main" java.lang.Error: Unresolved compilation problem: The local variable arr may not have been initialized
-
-
数组变量初始化
-
数据类型[] 数组名 = new 数据类型[数组长度];
初始化后所有元素的默认值:
数据类型 默认值 byte,short,int,long 0 float,double 0.0 boolean false char ‘\0’(即‘ ’,‘\u0000’ ,打印出空格) 所有引用数据类型 null -
数据类型[] 数组名 = new 数据类型[]{数组元素...};
不能在方括号中定义数组长度,编译时自动计算得出数组的长度。
int[] a = new int[3]{1,2,3}; //Error:此时不能在方括号中定义数组长度.
-
数据类型[] 数组名 = {数组元素...};
静态初始化:不能用于赋值
int[] arr = {1,2,3}; //只能在定义数组时使用 arr = {1,2,3}; //Error:不能用于直接赋值
编译时自动计算得出数组的长度
-
-
访问数组元素:
数组名[下标];
下标的取值范围:[0,数组长度)
下标如果超出范围将引发异常:
java.lang.ArrayIndexOutOfBoundsException
-
数组长度
int len = 数组名.length;
数组的长度在创建后是不可改变的
-
null与NullPointerException异常
数组变量如果没有具体的引用时,可以让其赋值为null,表示该数组变量没有指向任何数组对象
int[] arr = null; // arr[5] =10; // System.out.println(arr.length); // 都是java.lang.NullPointerException异常
二维数组
二维数组本质上和一维数组没有区别,只不过它存储的是一维数组的地址信息
使用
-
声明
数据类型[][] 数组名;
-
初始化
-
数据类型[][] 数组名 = new 数据类型[二维数组长度][];
- 二维数组已完成初始化
- 二维数组中存储的元素是null
- 二维数组存储的所有一维数组都没有完成初始化,如果访问一维数组,将抛出空指针异常
int[][] arr = new int[3][]; //只指定了二维数组的长度。一维数组的长度未知,因此一维数组没有进行初始化 System.out.println(arr[0]); //out:null 没有指定一维数组的长度,所以一维数组没有初始化,因此二维数组存储的数组默认为null System.out.println(arr[0][0]); //Error:java.lang.NullPointerException
-
数据类型[][] 数组名 = new 数据类型[二维数组长度][一维数组长度];
注意:
- 二维数组存储的所有一维数组的长度都相同
- 总共创建了(二维数组长度+1)个数组
- 所有的数组都已经完成初始化
- 二维数组中存储的元素是一维数组的地址信息
-
数据类型[][] 数组名 = new 数据类型[][]{{数组元素...},{数组元素...},{数组元素...},...};
注意:
- 不能在方括号中定义数组长度
- 编译时自动计算得出所有数组的长度
-
数据类型[][] 数组名 = {{数组元素…},{数组元素…},{数组元素…},…};
int[][] brr = {{1,2},{3,4,5},{6,7,8,9}}; //只能在定义数组时使用 brr = {{1,2},{3,4,5},{6,7,8,9}}; //Error:不能用于直接赋值
注意:
- 编译时自动计算得出所有数组的长度
- 只能在定义时使用,不能用于赋值
-
-
访问数组元素
二维数组存储的一维数组的长度可以不相同
//接上代码 arr[0] = new int[4]; arr[1] = new int[5]; int x = arr[0][0]; //out:0 默认初始化为0
-
数组长度
//接上代码 System.out.println(arr.length); //out:3 二维数组的长度 System.out.println(arr[0].length); //out:4 二维数组存储的第1个一维数组的长度 System.out.println(arr[2].length); //Error:空指针异常,二维数组存储的第3个一维数组未完成初始化 int y = arr[2][0]; //Error:同上
数组在内存中的存储方式
Java中:
- 数组名存储的是数组的地址信息,数组名存储在JVM内存的栈中。数组对象存储在JVM内存的堆中。所有对象都存储在堆中,且对象之间是不连续的,数组是一段连续的内存。
- 访问数组对象、元素时,其实是通过数组名存储的地址信息,找到存储在堆中的数组对象,然后获取响应元素。
- 对于二维数组(本质是一个存储多个一维数组的一维数组),数组名存储的是二维数组的地址信息,访问数组对象、元素时,其实是通过数组名存储的地址信息,找到存储在堆中的二维数组对象。这个二维数组存储的是一维数组的地址信息,再通过这个地址信息去访问堆中的一维数组对象。
C中:
-
数组名是数组的首地址指针。通过下标即可完成对数组的访问:
int arr[m] = {}; //假设数组的首地址为1000,arr[i]的地址为:1000 + 4(int类型字节数)* i
-
不同于Java,c中的二维数组在内存中是连续的
int arr[m][n] = {}; 假设数组的首地址为1000,arr[i][j]的地址为:1000 + 4(int类型字节数)* i * n + 4(int类型字节数 * j
数组作为方法的参数
- 基本数据类型作为方法参数时,在方法中修改形参,不会影响实参。
- 数组是引用数据类型,数组名存储的是数组的地址信息。当数组(引用类型对象)作为方法的实参进行传递时,方法形参的获取的其实是数组的地址信息。因此在方法中修改形参数组,实参数组也会随之改变。
数组的方法
在java.util.Arrays和java.lang.System下
-
String toString(int[] a):
打印数组所有元素
-
String deepToString(Object[] a) :
打印多维数组所有元素
-
int[] copyOf(int[] original, int newLength):
从数组original拷贝newLength个元素到另外一个数组中,返回该新数组。该方法常用于数组扩容
- newLength <= original.length 只拷贝前newLength个元素
- newLength > original.length 除了拷贝original中所有的元素以外,其它的元素用默认值在末尾填充至newLength长度
-
void arraycopy(Object src, int srcPos,Object dest, int destPos,int length)
从源src数组的srcPos下标位置拷贝length个元素到目标dest数组中并且从destPos下标存放 ,没有返回值
- 如果从源数组的srcPos位置开始不够length个元素,又或者目标数组dest的destPos下标位置开始不足以存放length个元素都将产生
java.lang.ArrayIndexOutOfBoundsException
- 如果从源数组的srcPos位置开始不够length个元素,又或者目标数组dest的destPos下标位置开始不足以存放length个元素都将产生