浅克隆:不会克隆对象中的引用类型属性,仅仅会把引用地址拷贝过来(也就是两者引用类型属性指向同一个地址)
深克隆:会克隆对象中的所有信息,原对象不会对新对象产生任何影响
浅克隆
测试:
Address类:作为Person类的一个属性
Person类:name属性、age属性、Address属性
测试类:测试深克隆与浅克隆
创建实体类
先创建一个地址类,只有城市一个属性
public class Address {
private String city;
public Address() {
}
public Address(String city) {
this.city = city;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address{" +
"city='" + city + '\'' +
'}';
}
}
创建人类,实现 Cloneable 接口,并重写 clone() 方法
将地址类Address也作为人类的一个属性
public class Person implements Cloneable{
private String name;
private int age;
private Address address;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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 Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address=" + address +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
主方法测试
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person("机器人", 3);
Address address = new Address("北京");
person1.setAddress(address);
// 克隆
Person person2 = (Person) person1.clone();
// 打印对象信息,及其hashCode
System.out.println("person1: " + person1);
System.out.println("person2: " + person2);
System.out.println("person1 hashCode: " + person1.hashCode());
System.out.println("person2 hashCode: " +person2.hashCode());
System.out.println("-------------------------------------");
// 打印对象中地址对象的信息,及其hashCode
System.out.println("person1 address: " + person1.getAddress());
System.out.println("person2 address: " + person2.getAddress());
System.out.println("person1 address hashCode: " + person1.getAddress().hashCode());
System.out.println("person2 address hashCode: " + person2.getAddress().hashCode());
}
}
结果
person1: Person{name='机器人', age=3, address=Address{city='北京'}}
person2: Person{name='机器人', age=3, address=Address{city='北京'}}
person1 hashCode: 1625635731
person2 hashCode: 1580066828
-------------------------------------
person1 address: Address{city='北京'}
person2 address: Address{city='北京'}
person1 address hashCode: 491044090
person2 address hashCode: 491044090
两个对象的值一样,因为是克隆过来的
两个对象的hashCode不一样,因为克隆之后是两个对象,所以hashCode不一样
两个对象中的对象属性address的值相同、hashCode相同,说明address不是克隆过来的
- 如果两个属性对象克隆成功,那么它们应该是两个对象,hashCode应该是不同的
- 而此时两者的hashCode相同,说明此属性对象并不是克隆过来的,person2中的address属性其实还是person1中的属性
注:此图只助于理解
以上实现的就是浅克隆,如果将一个对象中的属性对象也克隆过来,就是深克隆
那么如何实现深克隆?
深克隆
实现person的克隆需要实现Cloneable接口并重写clone()方法,那么再实现person中的address对象属性的克隆也是类似
实现Cloneable接口并重写clone()方法
public class Address implements Cloneable{
// ......
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
重写Person中的clone()方法
@Override
public Object clone() throws CloneNotSupportedException {
// 实现浅克隆
Person person = (Person) super.clone();
// 实现深克隆
person.setAddress((Address) address.clone());
return person;
}
再次运行
person1: Person{name='机器人', age=3, address=Address{city='北京'}}
person2: Person{name='机器人', age=3, address=Address{city='北京'}}
person1 hashCode: 1625635731
person2 hashCode: 1580066828
-------------------------------------
person1 address: Address{city='北京'}
person2 address: Address{city='北京'}
person1 address hashCode: 491044090
person2 address hashCode: 644117698
此时person中的两个对象属性的hashCode已经不一样了,因为它也被克隆过来了,所以是两个对象,hashCode自然不同
注:此图只助于理解
以上就完成了对象的深克隆
此时person中的两个对象属性的hashCode已经不一样了,因为它也被克隆过来了,所以是两个对象,hashCode自然不同