Java资源分享网 - 专业的Java学习网站 学Java,上Java资源分享网
《剑指offer》Java浅拷贝和深拷贝 PDF 下载
发布于:2024-03-06 09:39:02
(假如点击没反应,多刷新两次就OK!)

《剑指offer》Java浅拷贝和深拷贝 PDF 下载 图1

 

 

 

资料内容:

 

关于浅拷贝和深拷贝 浅拷贝和深拷贝其实就是在 引用 的这个基础上来做区分的,如果在拷贝的时候,只对基本数据类型进行 拷贝,对引用数据类型只是进行了引用的传递,没有真正的创建一个新的对象,这种拷贝方式就认为 是 浅拷贝 。反之,在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变 量,这种拷贝方式就被认为是 深拷贝 。 浅拷贝 那么如何实现 浅拷贝(Shallow copy) 呢?很简单,就是在需要拷贝的类上实现 Cloneable 接口并重写其 clone() 方法就可以了。 下面我们对 Food 类进行修改,我们让他实现 Cloneable 接口,并重写 clone() 方法。 public class Food implements Cloneable{ ... @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } ... } 然后在测试类中的代码如下 Food milk = new Food("milk",1,"fragrance"); Food food = (Food)milk.clone(); System.out.println("milk = " + milk); System.out.println("food = " + food); 可以看到,现在的 food 对象是由 milk 对象拷贝出来的,那么此时的 food 对象和 milk 对象是同一个对 象吗?我们通过打印,可以看到这两个对象的原生 hashcode 。 milk = com.cxuan.objectclone.Food@3cd1a2f1 food = com.cxuan.objectclone.Food@4d7e1886 可以发现,food 和 milk 并不是同一个对象,那 milk 中还有三个属性值,这三个属性值在 food 中是不 是也一样呢?为了验证这个猜想,我们重写了 toString 方法。 @Override public String toString() { return "Food{" + "name='" + name + '\'' + ", num=" + num + ", taste='" + taste + '\'' + '}'; } 然后再次打印 food 和 milk ,可以观察到如下结果 milk = Food{name='milk', num=1, taste='fragrance'} food = Food{name='milk', num=1, taste='fragrance'} 嗯哼,虽然看起来"cxuan 哥"和"cuan 哥"是两种完全不同的称呼!但是他们却有一种共同的能力:写 作! 我们还是通过图示来说明一下: 这幅图看出门道了么?在堆区分别出现了两个 Food 对象,这同时表明 clone 方法会重新创建一个对象 并为其分配一块内存区域;虽然出现了两个对象,但是两个对象中的属性值是一样的,这也是换汤不换 药,虽然汤和药是不同的东西(对象),但是他们都溶于水(属性值)。 深拷贝 虽然浅拷贝是一种换汤不换药的说法,但是在 Java 世界中还是有一种说法是。。。。。。是啥来着? 词穷了。。。。。。 哦对,还有一种改头换面的形式,它就是我们所熟悉的 深拷贝(Deep copy) ,先来抛出一下深拷贝的定 义:在进行对象拷贝的基础上,对对象的成员变量也依次拷贝的方式被称为深拷贝。 哈哈哈哈,这故作高深的深拷贝原来就是在浅拷贝的基础上再复制一下它的属性值啊,我还以为是啥高 深的东西呢!上代码! 我们先增加一个饮品类 Drink 。 public class Drink implements Cloneable { String name; get and set() @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } toString() } 然后更改一下 Food 类,因为 Drink 也算是 Food ,所以我们在 Food 类中增加对 Drink 的引用,然后再 修改 get set 、toString 、clone 、构造方法,修改后的 Food 类代码如下 public class Food implements Cloneable{ String name; int num; String taste; Drink drink; public Food(String name, int num, String taste,Drink drink) { this.name = name; this.num = num; this.taste = taste; this.drink = drink; } get and set... @Override protected Object clone() throws CloneNotSupportedException { Food food = (Food)super.clone(); food.drink = (Drink) drink.clone(); return super.clone(); } @Override public String toString() { return "Food{" + "name='" + name + '\'' + ", num=" + num + ", taste='" + taste + '\'' + ", drink=" + drink + '}'; } } 可以看到最大的改变是 clone 方法,我们在 clone 方法中,实现了对 Food 对象的拷贝,同时也实现了 对 Drink 对象的拷贝,这就是我们上面所说的复制对象并复制对象的成员变量。