【基础】- 对象克隆

2020-07-27  本文已影响0人  lconcise

为什么?

想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆。
Java中的克隆是针对的是类的实例。

如何实现克隆(两种方式)

  1. 实现Cloneable接口并重写Object类中的clone()方法。
  2. 实现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=西安市}
上一篇 下一篇

猜你喜欢

热点阅读