美文网首页
【基础】- 对象克隆

【基础】- 对象克隆

作者: lconcise | 来源:发表于2020-07-27 09:20 被阅读0次

为什么?

想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆。
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=西安市}

相关文章

  • 【基础】- 对象克隆

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

  • C4D完全自学实践指南(六 -Ⅳ ):克隆基础原理

    克隆基础 运动图形-克隆,新建立方体,拖动到克隆子集。 (1)对象属性 模式选择对象,新建一个圆环,将大纲里的圆环...

  • PHP中对象的复制

    潜克隆(浅拷贝) 只能克隆对象的"非对象非资源"数据。但如果对象中属性存储的是对象类型,就可以看到克隆没有克隆对象...

  • 对象的克隆

    对象的克隆 对象地址的引用: 以上属于对象地址的引用: 一、对象的浅克隆 Person: Demo: 对象浅克隆要...

  • 理解Java浅克隆和深克隆

    克隆概念 Java一切皆对象,克隆就是对对象的克隆;克隆可能听起来有点高级,也可以为对象复制或者对象拷贝。平时开发...

  • 前端小白必备资料之对象克隆篇

    对象的深浅克隆 对象的浅克隆 通过遍历 将obj1中的数据克隆到obj2当中 这种克隆只能克隆到对象中的基本数据类...

  • 4 创建型之原型模式

    概念 通过克隆(深拷贝)已存在的对象来创建新的对象。 解释 将已存在的对象作为原型,在对此原型进行克隆得到克隆对象...

  • 2019-03-02浅克隆和深克隆

    1.浅克隆 浅克隆,只是克隆了基本的数据类型,对于引用类型的对象只是复制了地址。在克隆后的新对象中,改变引用对象的...

  • Object的克隆

    克隆一个对象 浅克隆 浅克隆(也叫做浅拷贝)仅仅复制了这个对象本身的成员变量,该对象如果引用了其他对象的话,也不对...

  • 对象克隆

    实现Cloneable接口 实现Serializable接口 关键字transient--该元素不会进行jvm默认...

网友评论

      本文标题:【基础】- 对象克隆

      本文链接:https://www.haomeiwen.com/subject/qhmtlktx.html