深克隆:
public class Address implements Cloneable{
private String street;
public Address(String street) {
this.street = street;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
//Address类也要重写toString方法,不然输出是:User{age=10, name='Tom2', address=testpackage.Address2@424c0bc4}
@Override
public String toString() {
return "Address{" +
"street='" + street + '\'' +
'}';
}
//深度克隆:子类也需要重写该方法
@Override
protected Address clone() throws CloneNotSupportedException {
return (Address)super.clone();
}
}
public class User implements Cloneable {
private Integer age;
private String name;
private Address address;
public User() {
}
public User(Integer age) {
this.age = age;
}
public User(Integer age, String name) {
this.age = age;
this.name = name;
}
public User(Integer age, String name, Address address) {
this.age = age;
this.name = name;
this.address = address;
}
public User clone() throws CloneNotSupportedException {
User user = (User) super.clone();
user.address = address.clone();//深度克隆:父类的重写clone方法中带上子类的对象
return user;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
", address=" + address +
'}';
}
public Integer getAge() {
return age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address("大中路");
User u2 = new User();
u2.setAge(10);
u2.setName("Tom2");
u2.setAddress(address);
System.out.println(u2);
User u3 = u2.clone();
System.out.println(u3);
User u4 = u2.clone();
u4.setAge(40);
u4.setName("Tom4");
u4.setAddress(address);//深度clone后又把引用指向了原来的address,所以值与u2一致
System.out.println(u4);
address.setStreet("小中路");
System.out.println(u2);//属性变化
System.out.println(u3);//属性没变
System.out.println(u4);//属性变化
}
}
输出:
User{age=10, name='Tom2', address=Address{street='大中路'}}
User{age=10, name='Tom2', address=Address{street='大中路'}}
User{age=40, name='Tom4', address=Address{street='大中路'}}
User{age=10, name='Tom2', address=Address{street='小中路'}}
User{age=10, name='Tom2', address=Address{street='大中路'}}
User{age=40, name='Tom4', address=Address{street='小中路'}}
浅克隆:
把第三行注释掉,其他代码不变,
public User clone() throws CloneNotSupportedException {
User user = (User) super.clone();
// user.address = address.clone();//深度克隆:父类的重写clone方法中带上子类的对象
return user;
}
输出:
User{age=10, name='Tom2', address=Address{street='大中路'}}
User{age=10, name='Tom2', address=Address{street='大中路'}}
User{age=40, name='Tom4', address=Address{street='大中路'}}
User{age=10, name='Tom2', address=Address{street='小中路'}}
User{age=10, name='Tom2', address=Address{street='小中路'}}
User{age=40, name='Tom4', address=Address{street='小中路'}}
总结:
浅克隆是新的变量名(引用)依然指向原来的存储空间,使用原来的值,并没有开辟新的存储空间;
深克隆是开辟新的存储空间,新的变量名(引用)指向新的存储空间,并把原来的值复制过来。
浅克隆不开辟新的存储空间,只是复制值,
深克隆开辟新的存储空间,并且复制值。
如果针对一个不含有子类的类,克隆就应该是深克隆吧?
我觉得深克隆不是针对不含有子类的类说的,而是针对含有子类的类来说的,如果子类复制值了并且单独开辟了存储空间则是深克隆吧,如果子类只是复制值,没有单独开辟存储空间则是浅克隆吧?
子类指的是Integer、String那些基本引用类,同时也指自定义的类。
更多可见:
https://www.cnblogs.com/Qian123/p/5710533.html Java提高篇——对象克隆(复制)