1、典型回答
克隆是指创建一个对象的副本,使副本具有与原始对象相同的属性和状态。在计算机编程中,克隆是一种常见的操作,用于复制数据、对象或数据结构,以便在不影响原始数据的情况下进行操作、修改或分发。
克降最典型的使用场景是原型模式,原型模式是一种创建型设计模式,用于创建对象的克隆副本,而无需依赖复杂的实例化过程。原型模式通过复制现有对象的原型来创建新的对象,从而避免了通过构造函数创建对象的开销和复杂性。
而克隆又分为深克隆和浅克隆:
深克隆(Deep clone) 是将原型对象中的所有类型,无论是值类型还是引用类型,都复制一份给克降对象,也就是说深克隆会把原型对象和原型对象所引用的对象,都复制一份给克隆对象。
浅克隆(Shadow clone) 是把原型对象中成员变量为值类型的属性都复制给克隆对象,把原型对象中成员变量为引用类型的引用地址也复制给克降对象,也就是原型对象中如果有成员变量为引用对象,则此引用对象的地址是共享给原型对象和克降对象的。简单来说就是浅克隆只会复制原型对象,但不会复制它所引用的对象
深克隆和浅克隆的主要区别: 深克隆会复制原型对象和它所引用所有对象,而浅克隆只会复制原型对象
2、全面剖析
使用克降可以创建对象的克隆副本,而无需进行复杂的实例化过程。克隆分为深克隆和浅克隆,深克隆复制所有类型的属性,而浅克隆只会复制值类型和引用类型的引用地址副本(并未将引用类型本身克隆)
在 Java 中实现克隆,只需要实现 cloneable 接口,并重写 clone 方法即可,如下代码所示:
但在 Java 中,默认的克隆方式是浅克隆,想要实现深克隆需要遍历克隆对象中的所有引用类型成员变量,并对其(引用类型成员变量)也进行克隆操作,如下代码所示:
以上程序的执行结果如下:
原始对象: 小磊,25,北京
克隆对象: 磊哥,30,西安
从上述结果可以看出,引用类型 Address 并不是单纯的复制引用地址,而是这个复制了引用本身,因此修改了person2 之后,并未影响原始对象,说明它是深克隆。
3、知识扩展
深克降的实现除了可以手动将所有引用类型的属性实现克隆之外,还可以通过以下手动来实现:
- 使用序列化和反序列化:将对象写入字节流(序列化),然后从字节流中读取对象(反序列化)。而反序列化的过程,则是创建了一个新的副本对象,并且和原对象一模一样,但属性无论是值类型还是引用类型都是全新的,因此也实现了深克隆。
- 使用JSON 工具类实现深克隆:如 Jackson、Gson 或 FastJSON 等,这些JSON 具类本质上还是实现了序列化和反序列化(先将对象转换成JSON 字符,然后再将JSON 字符串转换成新对象),所以这种方式也是深克隆。下面是 Jackson 实现深克隆的示例代码:
以上程序执行结果如下:
3、使用第三方克隆工具类实现深克隆: 如 Apache Commons 库中的 SerializationUtils 类,它的实现代码如下:
以上程序执行结果如下: