## 一、场景 ###     酒店拼团需求中有一个复制报价的处理逻辑。需要复制 RoomPrice 对象 - ## 该类嵌套及其复杂,如果靠代码调用的方式复制,需要手写的复制逻辑比较多,且当类发生变化后,新的开发人员不一定能注意到去补充深拷贝的代码逻辑。 - ## 通过序列化、反序列化的方式能较为方便地实现深拷贝,但是其底层依赖反射,反序列化时需要类提供默认的构造器。 - ##   开发中初步采用了 Jackson 序列化的方式,但是在类的更改中由于新增的 Range 成员变量没有 Ignore,导致报错。 ## 二、调研 ![image.png|1000](https://cdn.jsdelivr.net/gh/Leoyishou/imageHosting@main/img/20231128155243.png) ## 三、目前结论 ###     使用 Kryo,无脑序列化,不需要特别注意什么 ![](https://wiki.corp.qunar.com/download/attachments/788295317/image2023-11-6_15-46-57.png?version=1&modificationDate=1699256817000&api=v2) ![](https://wiki.corp.qunar.com/download/attachments/788295317/image2023-11-6_15-53-44.png?version=1&modificationDate=1699257225000&api=v2) ## 四、思考 ### 4.1 非反射、递归手写 getset 的方式     一、clone 1. 需要递归地将整个 Object Tree 的所有类 `implements Cloneable`, 用深拷贝的方式重写 clone() 方法 2. effective java 不建议用 clone 1. 直接调 super.clone(),只能完成浅拷贝。 2. 要想深拷贝需要自己补充实现,但是这样的话递归关系嵌在了 object tree 上的每个 clone 方法里,容易受到 final 等修饰符的影响。自己实现每个地方的     二、写一个拷贝构造器 1. public MyClass(MyClass other) 自己实现方法,对于不可变对象或原始类型,直接复制其值即可;对于可变对象或数组,可能需要递归复制每个元素或子对象。     三、写一个拷贝工厂 public static MyClass newInstance(MyClass other)     总结: 1. **`Cloneable`**接口只能保证 clone 方法能用,但是不能约束 clone 的质量。clone() 将复制办法存在每个类中,不能保证每处的实现都满足深拷贝,比如 HashMap 2. 构造器或者工厂的方式,在一个地方统一约束递归关系 ### 4.2 反射、序列反序列化的方式     考虑的点:1. 空间、空间影响传输成本 2.时间 3.传输安全 4.一些类反序列化会出问题     在我们这个场景下,没有传输这件事,所以似乎只需要考虑时间的问题;range、pair 的问题 ## Reference [https://github.com/EsotericSoftware/kryo#without-maven](https://github.com/EsotericSoftware/kryo#without-maven) ![](https://wiki.corp.qunar.com/download/attachments/788295317/image2023-11-4_0-15-52.png?version=1&modificationDate=1699028152000&api=v2) Kryo 是一个高性能的序列化/反序列化工具,由于其变长存储特性并使用了字节码生成机制,拥有较高的运行速度和较小的字节码体积。 另外,Kryo 已经是一种非常成熟的序列化实现了,已经在 Twitter、Groupon、Yahoo 以及多个著名开源项目(如 Hive、Storm)中广泛的使用。