深拷贝与浅拷贝
在Java中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是两种复制对象的方法,它们在处理对象及其引用类型字段时有着不同的行为。下面简述两者的区别和如何使用深拷贝复制对象。
浅拷贝
浅拷贝是创建一个新对象,这个新对象是对原对象的字段逐个拷贝。如果原对象的某个字段是一个引用类型(例如指向一个对象的引用),浅拷贝只会复制这个引用,而不会复制引用的实际对象。这样,新对象和原对象将共享相同的引用类型字段。
class Address { String city; String street; Address(String city, String street) { this.city = city; this.street = street; } } class Person implements Cloneable { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); // 浅拷贝 } }
在上述代码中,Person
类实现了 Cloneable
接口,clone
方法调用了 super.clone()
,这将执行浅拷贝。新 Person
对象和原对象将共享相同的 Address
对象引用。
深拷贝
深拷贝不仅创建一个新对象,还递归地复制所有引用类型的字段对象。这样,新对象和原对象完全独立,它们之间没有共享的引用。
class Address implements Cloneable { String city; String street; Address(String city, String street) { this.city = city; this.street = street; } @Override protected Object clone() throws CloneNotSupportedException { return (Address) super.clone(); } } class Person implements Cloneable { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } @Override protected Object clone() throws CloneNotSupportedException { Person clonedPerson = (Person) super.clone(); clonedPerson.address = (Address) address.clone(); // 深拷贝地址 return clonedPerson; } }
在上述代码中,Person
类的 clone
方法不仅克隆自身,还克隆其引用类型字段 Address
,实现了深拷贝。
常见的深拷贝方法
除了手动实现 clone
方法外,还有其他几种实现深拷贝的方法:
1. 使用构造函数
通过创建一个新的构造函数来复制对象的所有字段。这种方法不需要实现 Cloneable
接口,但需要手动编写构造函数。
class Address { String city; String street; Address(String city, String street) { this.city = city; this.street = street; } // 深拷贝构造函数 Address(Address address) { this.city = address.city; this.street = address.street; } } class Person { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } // 深拷贝构造函数 Person(Person person) { this.name = person.name; this.address = new Address(person.address); } }
2. 使用 JSON 序列化和反序列化
通过将对象转换为 JSON 字符串,然后再将其解析为对象,可以实现深拷贝。需要使用第三方库如 Gson 或 Jackson。
import com.google.gson.Gson; class Address { String city; String street; Address(String city, String street) { this.city = city; this.street = street; } } class Person { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } } public class Main { public static void main(String[] args) { Gson gson = new Gson(); Address address = new Address("New York", "5th Avenue"); Person person1 = new Person("John", address); // 序列化为 JSON 字符串 String json = gson.toJson(person1); // 反序列化为新对象 Person person2 = gson.fromJson(json, Person.class); System.out.println(person1.address == person2.address); // false } }
3. 使用 Apache Commons Lang 的 SerializationUtils.clone(推荐)
这个方法非常简便,只不过需要确保所有参与深拷贝的类都实现 Serializable
接口。
import org.apache.commons.lang3.SerializationUtils; import java.io.Serializable; class Address implements Serializable { String city; String street; Address(String city, String street) { this.city = city; this.street = street; } } class Person implements Serializable { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } } public class Main { public static void main(String[] args) { Address address = new Address("New York", "5th Avenue"); Person person1 = new Person("John", address); Person person2 = SerializationUtils.clone(person1); System.out.println(person1.address == person2.address); // false } }
总结
在Java中,深拷贝和浅拷贝是两种不同的对象复制方式。浅拷贝只复制对象的引用,而深拷贝则递归复制所有引用类型的字段。选择适当的方法来实现深拷贝取决于具体的需求和上下文。以上几种方法各有优缺点,可以根据实际情况选择使用。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~