浅克隆与深克隆
Posted zoey686
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅克隆与深克隆相关的知识,希望对你有一定的参考价值。
深克隆与浅克隆的区别
一、clone()是什么
Object.clone()
clone是Object的方法,在使用clone()方法时需要调用Clonable这个接口,Cloneable()这个接口是一个空接口,在不实现Cloneable
接口的实例上调用对象的克隆方法导致抛出异常CloneNotSupportedException。
如果Clonable是个空接口,那么为什么还需要使用呢?
举个例子:如果一个对象不能被clone,则不实现Cloneable接口,如果有其它对象对此对象进行拷贝时,则会抛出CloneNotSupportedException。
所以说空接口即为标识接口,标识接口中没有任何方法的定义,其作用是告诉这些接口的实现类是否具有某个功能,比如是否支持克隆。
二、怎么clone
举个例子:
public class Person { String name; int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name=‘" + name + ‘‘‘ + ", age=" + age + ‘}‘; } }
public class NewPerson implements Cloneable { private String s; private int i; Person p; //上面的类 public NewPerson(String s, int i, Person p) { this.s = s; this.i = i; this.p = p; }
/*
进行Clone
所有类都默认继承Object,所以我们调用Clone是在调用父类的方法
*/
public NewPerson clone() { NewPerson np = null; try { np = (NewPerson) super.clone(); System.out.println("Supper: " + super.toString()); } catch (Exception e) { e.printStackTrace(); } return np; } @Override public String toString() { return "NewPerson{" + "s=‘" + s + ‘‘‘ + ", i=" + i + ", p=" + p + ‘}‘; } }
public class Main { public static void main(String[] args) { Person p = new Person("WangWu", 22); NewPerson p1 = new NewPerson("aaa", 1, p); NewPerson p2 = p1.clone(); System.out.println("p1: " + p1.toString()); //p1: Person{s=‘aaa‘, i=1, p=Person{name=‘WangWu‘, age=22}} System.out.println("p2: " + p2.toString()); //p2: Person2{s=‘aaa‘, i=1, p=Person{name=‘WangWu‘, age=22}}
///////////////////////////////////////////////////////////////////////////////////////////////////////// System.out.println(p1 == p2); //false System.out.println(p1.p == p2.p); //true } }
补充知识点: “==”比较地址,地址相同可表示同一个对象
现在你只需要看到//////上面,知道我们的clone调用成功了即可,并且知道如何使用clone
三、代码分析
p2 = p1.clone()
从输出的值我们可以知道p1 和 p2 的值相等
现在需要看////下面的输出了
p1 == p2 为 false: p1和p2的地址不同,不是同一个对象, 说明clone并不是引用,而是的的确确又新建立了一个对象
p1.p == p2.p 为 true:p1.p和p2.p的地址相同,说明NewPerson 中引用对象Person 在Clone中没有新建立对象,即p2.p没有新建立对象,而是指向了原有的p1.p
总结:B = A.clone() , A调用clone方法,新创建一个对象B,B中基本类型与A的基本类型相等,但是对于A中的引用对象,B中不进行创建,而是引用A中的引用对象。
四、深克隆与浅克隆
浅克隆就是与clone方法一样,新创立一个克隆的对象,但对于被克隆对象中的引用对象却不创建,而是引用被克隆对象中的。
深克隆也是创建一个对象,但是被克隆对象中的引用对象也会被重新创建。
图中即为上面代码深克隆和浅克隆的示意图
浅克隆 p1, p2对象都指向 p, 深克隆则是新创建了一个p
五、序列化实现深克隆
序列化与克隆一样也有一个空接口:Serializable
序列化:是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。是java提供的一种保存对象状态的机制。
序列化的使用场景:①将内存中对象保存到一个文件中或数据库中 ②将对象通过网络进行传播的时候
演示代码:
package com.zoey.java.clone; import java.io.Serializable;
//Person也需要继承Serializable接口,因为将NewPerson写入流中,也要讲Person写入流 public class Person implements Serializable { String name; int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name=‘" + name + ‘‘‘ + ", age=" + age + ‘}‘; } }
package com.zoey.java.clone; import java.io.*; public class NewPerson implements Serializable { Person p; int i; String s; public NewPerson(Person p, int i, String s) { this.p = p; this.i = i; this.s = s; } public Object deepClone() throws IOException, ClassNotFoundException { //将对象写入流中 ByteArrayOutputStream bao = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bao); oos.writeObject(this); //将对象从流中取出 ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return (ois.readObject()); } @Override public String toString() { return "NewPerson{" + "p=" + p + ", i=" + i + ", s=‘" + s + ‘‘‘ + ‘}‘; } }
package com.zoey.java.clone; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException, ClassNotFoundException { Person p = new Person("WangWu", 22); NewPerson p1 = new NewPerson(p,1,"aaa"); NewPerson p2 = (NewPerson) p1.deepClone(); System.out.println("p1: " + p1.toString()); System.out.println("p2: " + p2.toString()); System.out.println(p1 == p2); //false System.out.println(p1.p == p2.p); //false } }
均不相等说明都创建了新的引用对象,而不是同一个引用
以上是关于浅克隆与深克隆的主要内容,如果未能解决你的问题,请参考以下文章