Java中的对象拷贝主要分为:浅拷贝(Shallow Copy)、深拷贝(Deep Copy)。
在堆内存中不会分配新的空间,而是增加一个引用变量和之前的引用指向相同的堆空间。
详释:
①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。
②对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。
实例:
int[] a = {1,2,3,4,5};
int[]b = a;
public class Test {
public static void main(String[] args) {
//数组的浅拷贝,a,b两个引用指向同一个数组
int[] a = {1,2,3,4,5};
int[] b = a;
for (int i = 0; i < b.length; i++) {
System.out.print(b[i] + " ");
}
System.out.println();
}
}
在堆内存中分配新空间,将之前的数组堆内存中的内容拷贝到新的空间中。
详释:
对于深拷贝来说,不仅要复制对象的所有基本数据类型的成员变量值,还要为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象图进行拷贝!
实例:
int[] a = {1,2,3,4,5};
int[] b = new int[5];
System.arraycopy(a, 0, b, 0, 5);
public class Test {
public static void main(String[] args) {
//数组的深拷贝,a,b两个引用指向同一个数组
int[] a = {1,2,3,4,5};
int[] b = new int[5];
/**
* System.arraycopy(src, srcPos, dest, destPos, length);
* src:源数组
* srcPos:源数组中拷贝的起始位置
* dest:目标数组
* destPos:目标数组中开始存放的位置
* length:拷贝的长度
*/
System.arraycopy(a, 0, b, 0, a.length);
for (int i = 0; i < b.length; i++) {
System.out.print(b[i] + " ");
}
System.out.println();
}
}
注意
基本数据类型是值传递,所以修改值后不会影响另一个对象的该属性值;
引用数据类型是地址传递(引用传递),所以修改值后另一个对象的该属性值会同步被修改。
String类型非常特殊,首先,String类型属于引用数据类型,不属于基本数据类型,但是String类型的数据是存放在常量池中的,也就是无法修改的!