Java数组的存储方式
不同于基本数据类型,Java中的数组是一种引用类型。而在JVM中,栈内存存储变量,堆内存中存储变量值。
一维数组的存储
如图所示,JVM的栈内存中存储一个
I
n
t
e
g
e
r
Integer
Integer类型的数组变量
a
a
a,该引用指向堆内存中的一块连续空间@4d41cee
,该内存存储数组变量的值。
举例:
Integer [] a = {1,2,3};
System.out.println(a);
根据结果可以看出,变量 a a a指向内存中的一个固定区域。
二维数组的存储
Java中所有数组的本质其实都是一维数组,对于二维数组,只是在一维数组中存储了一个数组而已。
举例
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二维数组的每一个元素中存储的都是一个内存地址,该内存地址指向一个一维数组。
浅拷贝
浅拷贝指的是,在拷贝时,只是拷贝数组的内存地址,而非数组的实际值。
由于拷贝的是内存地址,浅拷贝会导致一个问题,在改变拷贝值时,原数组的值也会随之改变,因为二者指向同一块内存区域。
举例:
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));
通过 ‘=’ 实现浅复制,改变复制值 b b b的第一个值 b [ 0 ] b[0] b[0]后,原始数组 a [ 0 ] a[0] a[0]也随之改变,因为二者指向同一个内存地址,大家可以自行打印数组的内存地址进行确认。
深拷贝
深拷贝指的是,在拷贝时,拷贝数组的每一个值,而非数组在内存中的地址。
深拷贝则相反,由于拷贝的实际值,在改变拷贝值时,不会影响原始数组中的值,因为原始值和拷贝值分别指向两个不同的内存地址。
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));
通过 A r r a y s . c o p y O f ( a , a . l e n g t h ) Arrays.copyOf(a,a.length) Arrays.copyOf(a,a.length)实现深拷贝,将原始数组的每一个值都拷贝给一个新数组。在改变新数组的值时,原始数组的值不会受到影响。
深拷贝和浅拷贝的实现方式
深拷贝(拷贝值):
方式一:Arrays.copyOf(a,a.length);
方式二:b[i] = a[i];
方式三:b = a.clone();
方式四:System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
其中,如果数组是二维数组,需要对每一个子数组进行操作,对一维数组则直接操作。
浅拷贝(拷贝地址):
实现方式:=