【Java】Java 中实现深拷贝

浅拷贝 和 深拷贝

浅拷贝:只复制一层,如果对象的属性是引用数据类型,只会复制属性内存地址。
深拷贝:不只复制一层,如果对象属性是引用数据类型,会继续向下进行复制。

深拷贝的实现方法

1. 实现 Cloneable 接口

Artist.class

public class Artist implements Cloneable{
    /**
     * 姓名
     */
    private String name;
    /**
     * 年龄
     */
    private int age;

    public Artist(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public Artist clone() {
        try {
            Artist clone = (Artist) super.clone();
            // TODO: copy mutable state here, so the clone can't change the internals of the original
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}

Music.class

public class Music implements Cloneable{
    /**
     * 音乐名称
     */
    private String title;
    /**
     * 所属专辑
     */
    private String album;
    /**
     * 作曲人
     */
    private Artist artist;

    public Music(String title, String album, Artist artist) {
        this.title = title;
        this.album = album;
        this.artist = artist;
    }

    @Override
    public Music clone() {
        try {
            Music clone = (Music) super.clone();
            // TODO: copy mutable state here, so the clone can't change the internals of the original
            clone.artist = this.artist.clone();
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}

Music 类中的 artist 属性是 Artist类,MusicArtist 都要实现 Cloneable 接口,并且重写 clone() 方法

2. 序列化

每一个被拷贝的类都要实现 Serializable 接口

//深拷贝
public Object deepCopy() throws Exception{
    // 序列化
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);

    oos.writeObject(this);
    oos.flush();

    // 反序列化
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream ois = new ObjectInputStream(bis);

    return ois.readObject();
}

无法序列化使用 transient 修饰的属性

总结

  1. 序列化不需要每个类都重写 clone() 方法
  2. 序列化的效率比实现 Cloneable 接口的方法慢

参考:https://www.cnblogs.com/ysocean/p/8482979.html
https://juejin.cn/post/6844903806577164302#heading-11

posted @ 2022-12-14 16:36  HypoPine  阅读(1978)  评论(0编辑  收藏  举报