所谓的浅克隆,顾名思义就是很表面的很表层的克隆,如果我们要克隆Administrator对象,只克隆他自身以及他包含的所有对象的引用地址。
而深克隆,就是非浅克隆。克隆除自身以外所有的对象,包括自身所包含的所有对象实例。至于深克隆的层次,由具体的需求决定,也有“N层克隆”一说。
但是,无论所有的基本(primitive)类型数据是浅克隆还是深克隆,都会进行原值克隆。毕竟他们都不是对象,不是存储在堆中。注意:基本数据类型并不包括他们对应的包装类。
public class Address implements Cloneable{
private String state; //表示员工所在的国家
private String province;//表示员工所在的省份
private String city; //表示员工所在的城市
public Address(String state, String province, String city) {
super();
this.state = state;
this.province = province;
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
/*@Override
protected Object clone() throws CloneNotSupportedException {
Object o = super.clone();
return o;
}*/
@Override
public String toString() {
return "Address [state=" + state + ", province=" + province + ", city="
+ city + "]";
}
}
//其实下面就是Cloneable的接口内容,空无一物,只是用来表示这个类可以clone而已
/* package java.lang;
public interface Cloneable {
}
*/
//下面是Object类的方法,clone来自于Object类
/*public class Object {
private static native void registerNatives();
static {
registerNatives();
}
public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
timeout++;
}
wait(timeout);
}
public final void wait() throws InterruptedException {
wait(0);
}
protected void finalize() throws Throwable { }
}*/
public class Employee implements Cloneable {
private String name; //员工的姓名
private String age; //员工的年龄
Address address; //员工的地址
public Employee(String name, String age, Address address) {
super();
this.name = name;
this.age = age;
this.address = address;
}
/* 1. 让该类实现java.lang.Cloneable接口;
2. 确认持有的对象是否实现java.lang.Cloneable接口并提供clone()方法;
3. 重写(override)Object类的clone()方法,并且在方法内部调用持有对象的clone()方法;*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Employee employee = null;
employee = (Employee)super.clone();
//employee.address = (Address)employee.address.clone();
return employee;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("姓名:"+ name +" ,");
sb.append("年龄:"+ age +"\n");
sb.append("地址:"+ address);
return sb.toString();
}
}
import java.util.Date;
/**
*
* @author guoxiaoming
*我们发现当我们克隆之后(浅克隆),如果改变克隆之后对象的非引用值,那么克隆之前的对象不会发生改变,于是克隆非引用
*对象成功
*当我们改变克隆之后对象的引用值address的时候,原来对象里面的值也是跟着改变了,于是表明引用对象克隆不成功
*/
public class Test {
public static void main(String args[]) throws CloneNotSupportedException {
System.out.println("克隆之前:\n");
Address address = new Address("中国","安徽","阜阳");
Employee employee1 = new Employee("guoxiaoming","21",address);
System.out.println(employee1.toString());
Employee employee2 = (Employee)employee1.clone();
employee2.setAge("22");
employee2.setName("guoximing");
employee2.address.setCity("界首");
System.out.println("克隆之后employee1:");
System.out.println(employee1.toString());
System.out.println("克隆之后employee2:");
System.out.println(employee2.toString());
}
}
浅拷贝结果(Address 和Employee 里面的注释不去掉)
克隆之前:
姓名:guoxiaoming ,年龄:21
地址:Address [state=中国, province=安徽, city=阜阳]
克隆之后employee1:
姓名:guoxiaoming ,年龄:21
地址:Address [state=中国, province=安徽, city=界首]
克隆之后employee2:
姓名:guoximing ,年龄:22
地址:Address [state=中国, province=安徽, city=界首]
深拷贝(打开注释)
克隆之前:
姓名:guoxiaoming ,年龄:21
地址:Address [state=中国, province=安徽, city=阜阳]
克隆之后employee1:
姓名:guoxiaoming ,年龄:21
地址:Address [state=中国, province=安徽, city=阜阳]
克隆之后employee2:
姓名:guoximing ,年龄:22
地址:Address [state=中国, province=安徽, city=界首]
实现引用对象的成功拷贝,我们需要将引用对象也继承clonable接口,实现clone方法
然后在admin对象当中国的clone方法我们调用引用对象的clone方法,重新复制,两层拷贝