做内部优惠券网站赚钱吗,wordpress 100w 数据,pc网站设计哪家公司好,徐州百度快照优化在软件开发中#xff0c;克隆对象是一个常见需求。克隆的方式主要有两种#xff1a;深克隆#xff08;Deep Clone#xff09;和浅克隆#xff08;Shallow Clone#xff09;。了解它们的区别及其实现方法#xff0c;对于编写高效、安全的代码非常重要。
深克隆与浅克隆的…在软件开发中克隆对象是一个常见需求。克隆的方式主要有两种深克隆Deep Clone和浅克隆Shallow Clone。了解它们的区别及其实现方法对于编写高效、安全的代码非常重要。
深克隆与浅克隆的区别
浅克隆Shallow Clone 浅克隆会复制原型对象的基本数据类型的字段如int, float等而对于引用类型的字段如对象、数组等只会复制其引用地址。也就是说原型对象和克隆对象会共享引用类型的字段。
深克隆Deep Clone 深克隆不仅复制原型对象的基本数据类型字段还会递归复制引用类型的字段。这样原型对象和克隆对象在内存中是完全独立的不会共享任何引用类型的字段。
如何实现深克隆
深克隆的实现方式有多种下面介绍三种常见的方法
所有对象都实现克隆方法通过构造方法实现深克隆使用 JDK 自带的字节流实现深克隆
所有对象都实现克隆方法
这种方式要求所有引用类型的对象都实现Cloneable接口并重写clone方法。例如
public class CloneExample {public static void main(String[] args) throws CloneNotSupportedException {// 创建被赋值对象Address address new Address(001, 北京);People p1 new People(1, Java, address);// 克隆 p1 对象People p2 p1.clone();// 修改原型对象p1.getAddress().setCity(上海);// 输出 p1 和 p2 地址信息System.out.println(p1: p1.getAddress().getCity() p2: p2.getAddress().getCity());}static class People implements Cloneable {private Integer id;private String name;private Address address;Overrideprotected People clone() throws CloneNotSupportedException {People people (People) super.clone();people.setAddress(this.address.clone()); // 引用类型克隆赋值return people;}// getter 和 setter 方法public People(Integer id, String name, Address address) {this.id id;this.name name;this.address address;}}static class Address implements Cloneable {private Integer id;private String city;Overrideprotected Address clone() throws CloneNotSupportedException {return (Address) super.clone();}// getter 和 setter 方法public Address(Integer id, String city) {this.id id;this.city city;}}
}通过构造方法实现深克隆
《Effective Java》中推荐使用构造器来实现深克隆。构造器的参数为基本数据类型或字符串类型时直接赋值如果是对象类型则需要重新创建一个新的对象。
public class SecondExample {public static void main(String[] args) {// 创建对象Address address new Address(001, 北京);People p1 new People(1, Java, address);// 调用构造函数克隆对象People p2 new People(p1.getId(), p1.getName(), new Address(p1.getAddress().getId(), p1.getAddress().getCity()));// 修改原型对象p1.getAddress().setCity(上海);// 输出 p1 和 p2 地址信息System.out.println(p1: p1.getAddress().getCity() p2: p2.getAddress().getCity());}static class People {private Integer id;private String name;private Address address;// getter 和 setter 方法public People(Integer id, String name, Address address) {this.id id;this.name name;this.address address;}}static class Address {private Integer id;private String city;// getter 和 setter 方法public Address(Integer id, String city) {this.id id;this.city city;}}
}使用 JDK 自带的字节流实现深克隆
通过字节流实现深克隆的方式是将原型对象写入到内存中的字节流然后再从这个字节流中读出信息生成一个新对象。这个新对象与原型对象在内存地址上是完全独立的。
import java.io.*;public class ThirdExample {public static void main(String[] args) {// 创建对象Address address new Address(001, 北京);People p1 new People(1, Java, address);// 通过字节流实现克隆People p2 (People) StreamClone.clone(p1);// 修改原型对象p1.getAddress().setCity(上海);// 输出 p1 和 p2 地址信息System.out.println(p1: p1.getAddress().getCity() p2: p2.getAddress().getCity());}static class StreamClone {public static T extends Serializable T clone(People obj) {T cloneObj null;try {// 写入字节流ByteArrayOutputStream bo new ByteArrayOutputStream();ObjectOutputStream oos new ObjectOutputStream(bo);oos.writeObject(obj);oos.close();// 分配内存, 写入原始对象, 生成新对象ByteArrayInputStream bi new ByteArrayInputStream(bo.toByteArray());ObjectInputStream oi new ObjectInputStream(bi);// 返回生成的新对象cloneObj (T) oi.readObject();oi.close();} catch (Exception e) {e.printStackTrace();}return cloneObj;}}static class People implements Serializable {private Integer id;private String name;private Address address;// getter 和 setter 方法public People(Integer id, String name, Address address) {this.id id;this.name name;this.address address;}}static class Address implements Serializable {private Integer id;private String city;// getter 和 setter 方法public Address(Integer id, String city) {this.id id;this.city city;}}
}需要注意的是由于通过字节流序列化实现的深克隆每个对象必须实现Serializable接口否则会抛出异常。
总结
深克隆和浅克隆在对象复制上的区别主要在于是否复制引用类型的对象。浅克隆仅复制对象本身而深克隆会递归复制所有引用类型的对象。根据需求的不同可以选择实现Cloneable接口、使用构造器或者通过字节流进行深克隆。了解这些实现方法可以帮助我们在开发过程中更好地管理对象的复制和内存的使用。