JAVA深度拷贝遇到的坑

在ONE模拟器的使用中,我的某个功能需要将整个world都进行深度拷贝,但是world这个类里面包含了大量的自引用类,导致我在深度拷贝的时候踩了大量的坑,目前已经解决,这里进行回顾和总结,以防止遗忘。

1.JAVA深度拷贝方法的选择。查阅了网上关于java深度复制的方法,觉得序列化拷贝和利用JSON工具实现深度拷贝是两个比较好的方法。区别在于,利用序列化拷贝需要保证你拷贝的对象中,所有类(包括需要复制的对象本身)都必须实现 Serializable 这个类;而利用JSON进行拷贝,需要满足所有类都有全参和空构造方法,很巧world这个类以上两点一个都没满足,所有无论采用哪个工作量都不小,为了尽量减少对源代码的改动,我选择了利用序列化拷贝方法。

具体可参考:java中关于深拷贝的几种方式总结_java_脚本之家

关于序列化进行深度拷贝的方法,查到了一个对其进行封装的方法,但是找不到原地址了,这边直接放代码吧

public class CloneUtil {
    public CloneUtil(){}
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T cloneObject(T obj) {
        T cloneObj = null;

        // 序列化
        ByteArrayOutputStream bout = null;
        ObjectOutputStream oos = null;
        try {
            bout = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bout);
            oos.writeObject(obj);
        } catch (IOException e) {
            e.getStackTrace();
            System.out.println(e.toString());
        } finally {
            close(oos);
            close(bout);
        }

        // 反序列化
        ByteArrayInputStream bin = null;
        ObjectInputStream ois = null;
        try {
            bin = new ByteArrayInputStream(bout.toByteArray());
            ois = new ObjectInputStream(bin);
            cloneObj = (T) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println(e.toString());
        } finally {
            close(ois);
            close(bin);
        }

        return cloneObj;
    }

    private static void close(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

2.自引用类的深度拷贝。实际使用中,由于world中大量自引用类的存在,无论是序列化拷贝还是利用JSON拷贝,都会出现序列化过程中的循坏,即A->B->C->A,导致堆栈溢出。为了解决这个问题,我使用了 transient 修饰存在循坏的成员类,并在后续对其信息进行补充完善,整个过程可以理解为在解循坏,耗费了大量的精力。

ps:自引用类真的有点难顶啊

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值