2026-04-18 09:43:47
使用克隆的原因、实现方式及深拷贝与浅拷贝的区别如下:
一、为什么要使用克隆当需要对一个对象进行复制,同时保留原有对象以进行后续操作时,克隆是必要的。例如:
实现克隆主要有以下三种方式:
通过Cloneable接口和clone()方法
步骤:
实现Cloneable接口(标记接口,无方法)。
重写Object.clone()方法,将其访问权限改为public。
在clone()方法中调用super.clone()(浅拷贝)或手动实现深拷贝。
示例代码:
class MyClass implements Cloneable { private int value; private List<String> list; @Override public Object clone() throws CloneNotSupportedException { MyClass cloned = (MyClass) super.clone(); // 浅拷贝 // 深拷贝需手动复制引用类型字段 cloned.list = new ArrayList<>(this.list); return cloned; }}通过序列化实现深拷贝
步骤:
实现Serializable接口。
将对象序列化为字节流,再反序列化为新对象。
优点:自动处理引用类型,实现真正的深拷贝。
缺点:性能较低,需处理序列化异常。
示例代码:
import java.io.*;class DeepCopyUtil { public static <T extends Serializable> T deepCopy(T object) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(object); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); return (T) ois.readObject(); } catch (IOException | ClassNotFoundException e) { throw new RuntimeException("Deep copy failed", e); } }}使用工具类(如Apache Commons BeanUtils)
注意:工具类(如BeanUtils.copyProperties())通常实现浅拷贝。
示例:
import org.apache.commons.beanutils.BeanUtils;class Source { private String name; private List<String> items; // getters/setters}class Target { private String name; private List<String> items; // getters/setters}Source source = new Source();source.setName("Test");source.setItems(Arrays.asList("A", "B"));Target target = new Target();try { BeanUtils.copyProperties(target, source); // 浅拷贝} catch (Exception e) { e.printStackTrace();}浅拷贝(Shallow Copy)
定义:仅复制基本类型字段和引用类型字段的引用(内存地址),不复制引用指向的对象。
特点:
新对象与原对象共享引用类型字段,修改其中一个会影响另一个。
实现简单(如直接调用super.clone()或工具类)。
适用场景:对象无嵌套引用或无需独立修改引用类型字段时。
深拷贝(Deep Copy)
定义:复制基本类型字段和所有引用类型字段指向的对象(递归复制)。
特点:
新对象与原对象完全独立,修改互不影响。
实现复杂(需手动复制嵌套对象或通过序列化)。
适用场景:对象包含嵌套引用且需完全独立时。
对比总结

内存结构:浅拷贝中引用类型字段共享同一对象;深拷贝中引用类型字段指向新对象。
性能:浅拷贝更快,深拷贝因递归复制可能更耗时。
安全性:深拷贝更安全,避免意外修改共享数据。
简单场景用Cloneable接口(需注意浅拷贝问题)。
复杂嵌套对象用序列化或手动深拷贝。
快速开发可用工具类(但需确认是否为深拷贝)。
无需独立修改引用类型时用浅拷贝。
需完全隔离数据时用深拷贝。