Java数组的存储方式

不同于基本数据类型,Java中的数组是一种引用类型。而在JVM中,栈内存存储变量,堆内存中存储变量值。

一维数组的存储

Java 数组对象深拷贝 java二维数组深拷贝_java


如图所示,JVM的栈内存中存储一个Java 数组对象深拷贝 java二维数组深拷贝_开发语言_02类型的数组变量Java 数组对象深拷贝 java二维数组深拷贝_开发语言_03,该引用指向堆内存中的一块连续空间@4d41cee,该内存存储数组变量的值。

举例:

Integer [] a = {1,2,3};
System.out.println(a);

Java 数组对象深拷贝 java二维数组深拷贝_java_04

根据结果可以看出,变量Java 数组对象深拷贝 java二维数组深拷贝_jvm_05指向内存中的一个固定区域。

二维数组的存储

Java中所有数组的本质其实都是一维数组,对于二维数组,只是在一维数组中存储了一个数组而已。

Java 数组对象深拷贝 java二维数组深拷贝_数组_06


举例

Integer [][] c = {{1,2,3},{4,5,6},{7,8,9}};
System.out.println("c[0]:"+c[0]);
System.out.println("c[1]:"+c[1]);
System.out.println("c[0]:"+c[2]);

Java 数组对象深拷贝 java二维数组深拷贝_数组_07

Java二维数组的每一个元素中存储的都是一个内存地址,该内存地址指向一个一维数组。

浅拷贝

浅拷贝指的是,在拷贝时,只是拷贝数组的内存地址,而非数组的实际值。

由于拷贝的是内存地址,浅拷贝会导致一个问题,在改变拷贝值时,原数组的值也会随之改变,因为二者指向同一块内存区域。

举例:

Integer [] a = {1,2,3};
Integer [] b = a;
System.out.println(a);
System.out.println("修改前的b:"+Arrays.toString(b));
b[0] = 0;
System.out.println("修改数组第一个元素后:");
System.out.println("修改后的b:"+Arrays.toString(b));
System.out.println("修改后的a:"+Arrays.toString(a));

Java 数组对象深拷贝 java二维数组深拷贝_开发语言_08

通过 ‘=’ 实现浅复制,改变复制值Java 数组对象深拷贝 java二维数组深拷贝_开发语言_09的第一个值Java 数组对象深拷贝 java二维数组深拷贝_java_10后,原始数组Java 数组对象深拷贝 java二维数组深拷贝_开发语言_11也随之改变,因为二者指向同一个内存地址,大家可以自行打印数组的内存地址进行确认。

深拷贝

深拷贝指的是,在拷贝时,拷贝数组的每一个值,而非数组在内存中的地址。

深拷贝则相反,由于拷贝的实际值,在改变拷贝值时,不会影响原始数组中的值,因为原始值和拷贝值分别指向两个不同的内存地址。

Integer [] a = {1,2,3};
Integer [] b = Arrays.copyOf(a,a.length);
System.out.println(a);
System.out.println("修改前的b:"+Arrays.toString(b));
b[0] = 0;
System.out.println("修改数组第一个元素后:");
System.out.println("修改后的b:"+Arrays.toString(b));
System.out.println("修改后的a:"+Arrays.toString(a));

Java 数组对象深拷贝 java二维数组深拷贝_java_12

通过Java 数组对象深拷贝 java二维数组深拷贝_数组_13实现深拷贝,将原始数组的每一个值都拷贝给一个新数组。在改变新数组的值时,原始数组的值不会受到影响。

深拷贝和浅拷贝的实现方式

深拷贝(拷贝值):

方式一:Arrays.copyOf(a,a.length);
方式二:b[i] = a[i];
方式三:b = a.clone();
方式四:System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

其中,如果数组是二维数组,需要对每一个子数组进行操作,对一维数组则直接操作。

浅拷贝(拷贝地址):

实现方式:=