【JAVA基础面经】深拷贝与浅拷贝
文章目录基本概念浅拷贝深拷贝重写 clone() 方法实现深拷贝使用序列化实现深拷贝使用复制构造函数或工厂方法基本概念浅拷贝创建一个新对象然后将原对象的非静态字段基本类型和引用类型直接复制到新对象中。对于引用类型字段复制的是引用地址即新对象和原对象中的引用字段指向同一个实例。因此修改其中一个对象的引用字段内容会影响另一个对象。深拷贝创建一个新对象并递归地复制原对象中所有引用类型字段所引用的对象直到所有层次都被完全复制。新对象和原对象完全独立修改一个不会影响另一个。浅拷贝emap;默认的 super.clone() 执行的是浅拷贝此时p1 和 p2 的 address 引用指向同一个 Address 对象因此修改 p2 的地址会影响 p1classAddress{Stringcity;Address(Stringcity){this.citycity;}// getter/setter 省略}classPersonimplementsCloneable{Stringname;Addressaddress;Person(Stringname,Addressaddress){this.namename;this.addressaddress;}OverrideprotectedObjectclone()throwsCloneNotSupportedException{returnsuper.clone();// 浅拷贝}// getter/setter 省略}publicclassShallowCopyDemo{publicstaticvoidmain(String[]args)throwsCloneNotSupportedException{AddressaddrnewAddress(北京);Personp1newPerson(张三,addr);Personp2(Person)p1.clone();System.out.println(p1.address.city);// 北京System.out.println(p2.address.city);// 北京// 修改 p2 的地址p2.address.city上海;System.out.println(p1.address.city);// 上海 → 影响原对象System.out.println(p2.address.city);// 上海}}深拷贝重写 clone() 方法实现深拷贝在 clone() 方法中不仅要调用 super.clone()还要对引用类型字段手动进行拷贝通常也调用其 clone() 方法要求被引用的类也支持克隆。classAddressimplementsCloneable{Stringcity;Address(Stringcity){this.citycity;}OverrideprotectedObjectclone()throwsCloneNotSupportedException{returnsuper.clone();// Address 内部只有基本类型/不可变浅拷贝即可}}classPersonimplementsCloneable{Stringname;Addressaddress;Person(Stringname,Addressaddress){this.namename;this.addressaddress;}OverrideprotectedObjectclone()throwsCloneNotSupportedException{Personcloned(Person)super.clone();// 浅拷贝基础字段cloned.address(Address)address.clone();// 深拷贝 addressreturncloned;}}使用序列化实现深拷贝将对象写入流再从流中读出可以自动实现深拷贝要求所有引用类型都实现 Serializable 接口。序列化方式的优点是不需要为每个类手动编写拷贝逻辑但要求所有涉及类都实现 Serializable且性能相对较低。importjava.io.*;classAddressimplementsSerializable{Stringcity;Address(Stringcity){this.citycity;}}classPersonimplementsSerializable{Stringname;Addressaddress;Person(Stringname,Addressaddress){this.namename;this.addressaddress;}// 深拷贝方法publicPersondeepCopy(){try(ByteArrayOutputStreambosnewByteArrayOutputStream();ObjectOutputStreamoosnewObjectOutputStream(bos)){oos.writeObject(this);try(ByteArrayInputStreambisnewByteArrayInputStream(bos.toByteArray());ObjectInputStreamoisnewObjectInputStream(bis)){return(Person)ois.readObject();}}catch(IOException|ClassNotFoundExceptione){e.printStackTrace();returnnull;}}}使用复制构造函数或工厂方法手动编写一个构造函数接收同类型对象并逐一复制字段对于引用类型也递归复制。这种方式清晰直观但需要为每个类编写拷贝逻辑且当对象图复杂时容易遗漏。classAddress{Stringcity;Address(Stringcity){this.citycity;}// 复制构造函数Address(Addressother){this.cityother.city;}}classPerson{Stringname;Addressaddress;Person(Stringname,Addressaddress){this.namename;this.addressaddress;}// 复制构造函数深拷贝Person(Personother){this.nameother.name;this.addressnewAddress(other.address);// 复制 address}}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2471214.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!