深拷贝与浅拷贝

在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中,深拷贝和浅拷贝是两种不同的对象复制方式。浅拷贝只复制对象的引用,而深拷贝则递归复制所有引用类型的字段。选择适当的方法来实现深拷贝取决于具体的需求和上下文。以上几种方法各有优缺点,可以根据实际情况选择使用。

posted @   Cloong  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示