目录
1.数组的拷贝
整体拷贝
部份拷贝
模拟实现数组全拷贝与部份拷贝
2.深浅拷贝的概念
浅拷贝
深拷贝
4.深浅拷贝的应用
浅拷贝
深拷贝-两种实现方式
1)递归实现的Cloneable接口
2)通过序列化来进行拷贝
1.数组的拷贝
在看深浅拷贝前,首先来看数组的拷贝:
整体拷贝Arrays.copyOf(arr,arr.length);
import java.util.Arrays; public class AllCopy { public static void main(String[] args) { int[] arr={1,3,5,7,9}; int[] ret= Arrays.copyOf(arr,arr.length);//整体拷贝 ret[0]=10; arr[0]=4; System.out.println(arrStr(arr)); System.out.println(arrStr(ret)); } private static String arrStr(int[] arr) { String ret="["; for (int i = 0; i < arr.length; i++) { ret+=arr[i]; if(i!= arr.length-1) { ret += ","; } } ret+="]"; return ret; } }
结果:[4,3,5,7,9]
[10,3,5,7,9]
分析:这里的拷贝把所有值都拷贝过来了,是属于整体拷贝。也属于深拷贝(相对来说的,它这里只有基本数据类型(即只有一层),原数组完全不影响新建数组)就是说ret[0]=10不影响原来的arr[0],arr[0]=4不影响新拷贝的数组中的ret[0]。拷贝后的数组对象确实是个新对象,开辟了新空间,只是将原数组的内容复制给新数组,这也就算属于深拷贝范畴。
部份拷贝Arrays.copyOfRange(原数组名称,原数组起始位置,原数组结束位置)
起始位置和结束位置是左闭右开区间来取:[from,to)
import java.util.Arrays; public class AllCopy { public static void main(String[] args) { int[] arr={1,3,5,7,9}; int[] ret= Arrays.copyOfRange(arr,2,4);//部份拷贝 System.out.println(arrStr(arr)); System.out.println(arrStr(ret)); } private static String arrStr(int[] arr) { String ret="["; for (int i = 0; i < arr.length; i++) { ret+=arr[i]; if(i!= arr.length-1) { ret += ","; } } ret+="]"; return ret; } }模拟实现数组全拷贝与部份拷贝
public class AllCopy { public static void main(String[] args) { int[] arr={1,3,5,7,9}; int[] ret= arrCopy(arr);//全拷贝 int[] str=arrCopyRange(arr,2,4);//部份拷贝 ret[0]=10; System.out.println(arrStr(arr)); System.out.println(arrStr(ret)); System.out.println(arrStr(str)); } private static int[] arrCopy(int[] arr) { //实现数组全拷贝 int[] ret=new int[arr.length]; for (int i = 0; i < arr.length; i++) { ret[i]=arr[i]; } return ret; } private static int[] arrCopyRange(int[] arr,int start,int end) { //部份拷贝 int[] str=new int[end-start]; int j=0; for (int i = 0; i < arr.length; i++) { while(i==start&&start在观察数组拷贝的基础上了解深浅拷贝的概念:
2.深浅拷贝的概念 浅拷贝通过赋值的方式进行拷贝,只是把对象的表层赋给一个新的对象,拷贝后的对象和原对象仍指向同一块空间。此时原对象内部若有引用,则改变该引用的值,新对象中该引用的值也会随之变化。(外部开辟了新的空间内部并未开辟新空间,还是原来的)
浅拷贝对基本数据类型来说是值传递,对于引用类型来说,是进行引用传递般的拷贝,并未真实的创建一个新的对象。
深拷贝原对象的修改不会影响拷贝后的对象(内外都开辟了新的空间)
对基本数据类型来说是值传递,但是对于引用类型来讲,原对象内部若有引用,则创建一个新的对象,并复制其内成员变量等内容
【ps:什么是引用?引用就是给对象起了个名字,保存的是对象的地址】
4.深浅拷贝的应用 浅拷贝class A{ int num; } public class B implements Cloneable{ A a=new A(); @Override protected B clone() throws CloneNotSupportedException { return (B)super.clone(); } public static void main(String[] args) throws CloneNotSupportedException { B b1=new B(); B b2=b1.clone(); System.out.println(b1==b2); System.out.println(b2.a.num); b1.a.num=100; System.out.println(b2.a.num); } }结果:false
0
100分析:false说明b1,b2不是一个地址空间,b2实现了拷贝。而b1.a.num改变会影响b2.a.num的值,说明虽然b2是拷贝过来的,但是仍旧和b1指向同一块引用a,b1,b2中a的属性值是会同时改变的,实现了浅拷贝。
深拷贝-两种实现方式 1)递归实现的Cloneable接口就上面浅拷贝例子而言,若要把它改成深拷贝,则在其的代码基础上,可以给A也实现Cloneable接口,即给A也实现克隆方法(都克隆-都有新空间)
class A implements Cloneable{ int num; @Override protected A clone() throws CloneNotSupportedException { return (A)super.clone(); } } public class B implements Cloneable{ A a=new A(); @Override protected B clone() throws CloneNotSupportedException { B newB=(B)super.clone(); newB.a=a.clone();//让a也是克隆来的 return newB; } public static void main(String[] args) throws CloneNotSupportedException { B b1=new B(); B b2=b1.clone(); System.out.println(b1==b2); System.out.println(b2.a.num); b1.a.num=100; System.out.println(b2.a.num); } }结果:false
0
0分析:false说明b1b2是两个东西,开辟了新空间,b1中a.num改变影响不了b2中a.num,说明a也是被克隆了,开辟了新空间的,b1,b2内部包含的a确实不是一个对象,实现了深拷贝。
2)通过序列化来进行拷贝1.序列化:将一个对象转为字符串就叫做序列化
2.将对象转为json字符串(序列化)进行拷贝,所有的序列化都是深拷贝
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)