实现对象的深度克隆

梦想的初衷 提交于 2019-12-06 13:08:12

1.方式一

实现Cloneable接口并重写 Object类中的 clone()方法

2. 方式二

(实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆)

2.1 User类和Car的准备

package cn.qdm.ceshi;

import java.io.Serializable;

public class User  implements Serializable{
    private String name;
    private Integer age;
    
    private Car car; //开的车

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }

    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + ", car=" + car + "]";
    }

    public User(String name, Integer age, Car car) {
        super();
        this.name = name;
        this.age = age;
        this.car = car;
    }

    public User() {
        super();
        // TODO Auto-generated constructor stub
    }

}


package cn.qdm.ceshi;

import java.io.Serializable;

public class Car implements Serializable{
    private String brand; //品牌

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    @Override
    public String toString() {
        return "Car [brand=" + brand + "]";
    }

    public Car(String brand) {
        super();
        this.brand = brand;
    }

    public Car() {
        super();
        // TODO Auto-generated constructor stub
    }
    
}


2.2 克隆工具类的准备

package cn.qdm.ceshi;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class MyUtil {
    
    private MyUtil() {
        throw new AssertionError();
    }
    //实现深度克隆的工具方法
    
    public static<T extends Serializable> T clone(T obj) throws Exception{
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bout);
            oos.writeObject(obj);
            ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bin);
            return (T) ois.readObject();
            //ByteArrayOutputStream和ByteArrayInputStream是基于内存的流只要垃圾回收器清理对象就能够释放资源,不同于外部资源(如文件流)的释放
            
    }
}

2.3 测试类

package cn.qdm.ceshi;

public class CloneTest {
    public static void main(String[] args) {
        User user1 = new User("张三", 18, new Car("BYD"));
        //深度克隆
        try {
            User user2 = MyUtil.clone(user1);
            //修改克隆对象user2的关联汽车属性
            user2.getCar().setBrand("迈凯伦P1");
            //打印原来对象不影响关联对象
            System.out.println(user1);
            System.out.println(user2);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

2.4 运行结果

3.注意:

基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是用过泛型限定,可以检查出
要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种方案明显
优于使用Obeject类的clone方法克隆对象,让问题在编译的时候就暴露出来
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!