- 使用场景
当我们需要创建一个对象的副本的时候,并且在改变他们各自的内容的时候互不影响,就可以使用Object类中clone()方法 - 使用clone()方法需要注意
需要实现Cloneable接口,否则抛出CloneNotSupportedException
需要调用super.clone()
该方法实现"浅拷贝"而不是“深拷贝” - “浅拷贝”和“深拷贝”的区别
浅拷贝:被拷贝的对象中不含有其他实体类对象的引用
深拷贝:被拷贝对象中含有其他实体类对象的引用,那么这些实体类都需要实现Cloneable接口,实现clone()方法
浅拷贝
/**
* @Author: 保质期已过
* @Date: 2020/6/3 22:28
* Description:
* @Version 1.0
*/
@Data
@AllArgsConstructor(access = AccessLevel.PUBLIC)
public class Address{
private String addressName;
}
@Data
@AllArgsConstructor(access=AccessLevel.PUBLIC)
public class Person implements Cloneable {
private String name;
private int age;
//引用类型对象
private Address address;
//浅复制
public Person clone() throws CloneNotSupportedException {
return (Person)super.clone();
}
}
测试浅拷贝
@org.junit.jupiter.api.Test
public static void test01() throws CloneNotSupportedException {
Address address = new Address("成都");
Person person = new Person("张三",20,address);
Person person1 = person.clone();
System.out.println(person1.toString());
}
输出
Person(name=张三, age=20, address=Address(addressName=成都))
4.实体类对象拷贝问题
我们看到Address实体类对象的引用,也被复制过来了,其实这里只是复制了引用,并没有创建Address新的副本。执行如下测试代码,但我们在修改拷贝后person对象的Address中的addressName属性值时,拷贝前的person中的Address中的addressName属性值也被更改了
@org.junit.jupiter.api.Test
public void test02() throws CloneNotSupportedException {
Address address = new Address("成都");
Person person = new Person("张三",20,address);
Person person1 = person.clone();
person1.getAddress().setAddressName("武漢");
System.out.println("拷贝后的person:"+person1.toString());
System.out.println("拷贝前的person:"+person.toString());
}
输出
拷贝后的person:Person(name=张三, age=20, address=Address(addressName=成都))
拷贝前的person:Person(name=张三, age=20, address=Address(addressName=武漢))
深拷贝
改造Address类,也实现Cloneable接口,重写clone()方法
/**
* @Author: 保质期已过
* @Date: 2020/6/3 22:28
* Description:
* @Version 1.0
*/
@Data
@AllArgsConstructor(access = AccessLevel.PUBLIC)
public class Address implements Cloneable{
private String addressName;
public Address clone() throws CloneNotSupportedException {
return (Address) super.clone();
}
}
改造Person类,新增深拷贝的方法
/**
* @Author: 保质期已过
* @Date: 2020/6/3 21:45
* Description:
* @Version 1.0
*/
@Data
@AllArgsConstructor(access=AccessLevel.PUBLIC)
public class Person implements Cloneable {
private String name;
private int age;
//引用类型对象
private Address address;
//浅拷贝
public Person clone() throws CloneNotSupportedException {
return (Person)super.clone();
}
//深拷贝
public Person deepClone() throws CloneNotSupportedException {
Person person = (Person) super.clone();
Address newaddress = (Address) address.clone();
person.address = (Address) address.clone();
return person;
}
}
测试深拷贝
@org.junit.jupiter.api.Test
public void test03() throws CloneNotSupportedException {
Address address = new Address("成都");
Person person = new Person("张三",20,address);
Person person1 = person.deepClone();
person1.getAddress().setAddressName("武漢");
System.out.println("拷贝后的person:"+person1.toString());
System.out.println("拷贝前的person:"+person.toString());
}
输出
拷贝后的person:Person(name=张三, age=20, address=Address(addressName=武漢))
拷贝前的person:Person(name=张三, age=20, address=Address(addressName=成都))