问:深克隆和浅克隆的区别?
答:浅克隆是被克隆对象的所有变量都含有与原来对象相同的值,而所有对其他对象的引用仍然指向原来的对象。
深克隆是被克隆对象的所有变量都含有与原来对象相同的值,那些引用变量将指向被克隆的新对象,而不再是原有的那些被引用的对象。深克隆是把克隆的对象所引用的对象都克隆了一边。
浅克隆(ShallowClone)和深克隆(DeepClone)。
在Java语言中,数据类型分为值类型(基本数据类型)和引用类型,
值类型包括int、double、byte、boolean、char等简单数据类型,
引用类型包括类、接口、数组等复杂类型。
浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制。
实现clone方法的步骤
(1)实现Cloneable接口
(2)重写Object类中的clone()方法,重写时需定义为public
(3)在重写方法中,调用super.clone()
浅克隆
package yuanxingmoshi;
public class Address implements Cloneable{
private String dizhi;
public String getDizhi() {
return dizhi;
}
public void setDizhi(String dizhi) {
this.dizhi = dizhi;
}
public Address clone() {
Address a =null;
try {
a = (Address) super.clone();
return a;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
package yuanxingmoshi;
public class Customer implements Cloneable {
private Address address;
private String name;
private int age;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Customer clone() {
Customer o=null;
try {
o = (Customer) super.clone();
return o;
} catch (CloneNotSupportedException e) {
System.out.println("复制失败");
return null;
}
}
test
package yuanxingmoshi;
public class test {
public static void main(String[] args) {
Customer c_Previous = new Customer();
Address address = new Address();
address.setDizhi("杭州");
c_Previous.setAge(18);
c_Previous.setName("张无忌");
c_Previous.setAddress(address);
Customer c_new = c_Previous.clone();
address.setDizhi("北京");
System.out.println("f"+c_new.getAddress().getDizhi() + c_new.getAge() + c_new.getName());
System.out.println("f"+c_Previous.getAddress().getDizhi() + c_Previous.getAge() + c_Previous.getName());
}
}
结果为
f北京18张无忌
f北京18张无忌
深克隆方法一
package yuanxingmoshi;
public class Customer implements Cloneable {
private Address address;
private String name;
private int age;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Customer clone() {
Customer o=null;
try {
o = (Customer) super.clone(); //签复制
} catch (CloneNotSupportedException e) {
System.out.println("复制失败");
return null;
}
o.address = (Address) address.clone(); //深度复制
return o;
}
}
而此时结果为:
f杭州18张无忌
f北京18张无忌
深克隆方法二
解决多层克隆问题
如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含引用类型,使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。
package yuanxingmoshi;
import java.io.*;
public class Customer implements Cloneable, Serializable {
private Address address;
private String name;
private int age;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
/* public Customer clone() {
Customer o=null;
try {
o = (Customer) super.clone();
return o;
} catch (CloneNotSupportedException e) {
System.out.println("复制失败");
return null;
}
}
public Customer 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 (Customer) ois.readObject();
}
}
Test
package yuanxingmoshi;
import java.io.IOException;
public class test {
public static void main(String[] args) {
Customer c_Previous = new Customer();
Address address = new Address();
address.setDizhi("杭州");
c_Previous.setAge(18);
c_Previous.setName("张无忌");
c_Previous.setAddress(address);
Customer c_new = null;
try {
c_new = c_Previous.deepClone();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// Customer c_new = CloneUtil.cloneObject(c_Previous);
address.setDizhi("北京");
System.out.println("f"+c_new.getAddress().getDizhi() + c_new.getAge() + c_new.getName());
System.out.println("f"+c_Previous.getAddress().getDizhi() + c_Previous.getAge() + c_Previous.getName());
}
}
结果为
f杭州18张无忌
f北京18张无忌