为什么?
想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆。
Java中的克隆是针对的是类的实例。
如何实现克隆(两种方式)
- 实现Cloneable接口并重写Object类中的clone()方法。
- 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。
注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是优于把问题留到运行时。
深拷贝与浅拷贝
- 浅拷贝只是复制了对象的引用地址,两个对象指向同一内存地址,所以修改其中任意的值,另一值也会随之改变,这就是浅拷贝
- 深拷贝是将对象及值复制过来,两个对象修改其中任意的值另一值不会改变,这就是深拷贝
克隆方式一(实现Cloneable接口)
创建对象实现Cloneable接口,并重写clone方法
public class Student implements Cloneable {
private int number;
private Address address;
public Student() {
}
public Student(int number) {
this.number = number;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Student student = (Student) super.clone(); // 浅复制
student.address = (Address) address.clone(); // 深复制
return student;
}
@Override
public String toString() {
return "Student{" +
"number=" + number +
", address=" + address.getAddress() +
'}';
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
public class Address implements Cloneable {
private String address;
public Address() {
}
public Address(String address) {
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
测试:
public class MainDemo {
public static void main(String[] args) throws CloneNotSupportedException {
// 创建对象
Address address = new Address("西安市");
Student student = new Student(1);
student.setAddress(address);
// 克隆
Student clone = (Student) student.clone();
// 比较
System.out.println(student == clone);
// 修改其中一个对象的值
student.setNumber(111);
clone.setNumber(222);
student.getAddress().setAddress("西安市雁塔区");
System.out.println(student);
System.out.println(clone);
}
}
测试输出:
false
Student{number=111, address=西安市雁塔区}
Student{number=222, address=西安市}
实现Serializable接口
创建Student类,实现Serializable接口,编写自己clone方法
public class Student implements Serializable {
private static final long serialVersionUID = -8604204030828181807L;
private int number;
private Address address;
public Student() {
}
public Student(int number) {
this.number = number;
}
// 通过对象的序列化和反序列化实现对象克隆
public Student myClone() {
Student student = null;
try {
ByteArrayOutputStream byteOS = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(byteOS);
oos.writeObject(this);
ByteArrayInputStream byteIS = new ByteArrayInputStream(byteOS.toByteArray());
ObjectInputStream ois = new ObjectInputStream(byteIS);
student = (Student) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return student;
}
@Override
public String toString() {
return "Student{" +
"number=" + number +
", address=" + address.getAddress() +
'}';
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
public class Address implements Serializable {
private static final long serialVersionUID = 6119800206040740802L;
private String address;
public Address() {
}
public Address(String address) {
this.address = address;
}
@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
测试:
public class MainDemo {
public static void main(String[] args) throws CloneNotSupportedException {
// 创建对象
Address address = new Address("西安市");
Student student = new Student(1);
student.setAddress(address);
// 克隆
Student clone = (Student) student.myClone();
// 比较
System.out.println(student == clone);
// 修改其中一个对象的值
student.setNumber(111);
clone.setNumber(222);
student.getAddress().setAddress("西安市雁塔区");
System.out.println(student);
System.out.println(clone);
}
}
测试输出:
false
Student{number=111, address=西安市雁塔区}
Student{number=222, address=西安市}
网友评论