Java 中对象的复制:深拷贝与浅拷贝
在 Java 编程中,复制对象是一项常见的任务,尤其是在处理复杂数据结构时。对象的复制通常可以通过浅拷贝和深拷贝两种方式来实现。本文将深入探讨这两种拷贝方式,并通过代码示例进行说明。
什么是浅拷贝?
浅拷贝是指创建一个新对象,其内容与原对象相同,但对于子对象(引用类型),新对象和原对象仍然指向同一块内存区域。这意味着如果子对象的状态在其中一个对象中发生变化,另一个对象也会受到影响。
浅拷贝示例
下面是一个简单的示例,演示如何使用 Java 的 clone()
方法进行浅拷贝:
class Address {
String city;
public Address(String city) {
this.city = city;
}
}
class Person implements Cloneable {
String name;
Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class ShallowCopyExample {
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address("New York");
Person person1 = new Person("Alice", address);
Person person2 = (Person) person1.clone();
System.out.println("Before changing address:");
System.out.println("person1 address: " + person1.address.city);
System.out.println("person2 address: " + person2.address.city);
// 改变 person1 的地址
person1.address.city = "Los Angeles";
System.out.println("After changing address:");
System.out.println("person1 address: " + person1.address.city);
System.out.println("person2 address: " + person2.address.city);
}
}
运行结果
Before changing address:
person1 address: New York
person2 address: New York
After changing address:
person1 address: Los Angeles
person2 address: Los Angeles
如上所示,修改 person1
的地址后,person2
的地址也发生了变化。这就是浅拷贝的特征。
什么是深拷贝?
深拷贝则是指创建一个新对象,及其所有子对象均为新创建的对象。也就是说,新对象和原对象在内存中是完全独立的,彼此的状态变化不会互相影响。
深拷贝示例
下面是通过实现 Serializable
接口和使用对象流来实现深拷贝的示例:
import java.io.*;
// Address class
class Address implements Serializable {
String city;
public Address(String city) {
this.city = city;
}
}
// Person class
class Person implements Serializable {
String name;
Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
// 深拷贝
public Person deepClone() throws IOException, ClassNotFoundException {
// 将对象写入流
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(this);
// 从流中读取对象
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream in = new ObjectInputStream(byteIn);
return (Person) in.readObject();
}
}
public class DeepCopyExample {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Address address = new Address("New York");
Person person1 = new Person("Alice", address);
Person person2 = person1.deepClone();
System.out.println("Before changing address:");
System.out.println("person1 address: " + person1.address.city);
System.out.println("person2 address: " + person2.address.city);
// 改变 person1 的地址
person1.address.city = "Los Angeles";
System.out.println("After changing address:");
System.out.println("person1 address: " + person1.address.city);
System.out.println("person2 address: " + person2.address.city);
}
}
运行结果
Before changing address:
person1 address: New York
person2 address: New York
After changing address:
person1 address: Los Angeles
person2 address: New York
此示例中,修改 person1
的地址并未影响 person2
的地址,表现出了深拷贝的特征。
序列图解析
我们可以通过序列图更好地理解深拷贝过程。以下是深拷贝的序列图:
sequenceDiagram
participant A as Person1
participant B as Person2
participant C as ObjectOutputStream
participant D as ObjectInputStream
A->>C: Serialize Person1
C->>C: Write Object State
C->>B: Output Stream
D->>C: Input Stream
D->>B: Deserialize to Person2
实体关系图
在我们的例子中,Person
类和 Address
类之间的关系可以用一个实体关系图表示:
erDiagram
PERSON {
String name
}
ADDRESS {
String city
}
PERSON ||--o{ ADDRESS : has
总结
在 Java 中,了解浅拷贝和深拷贝的区别非常重要。浅拷贝适用于那些对象间共享状态没有负面影响的情况,而深拷贝则适用于需要完全独立的对象副本的情况。根据具体需求选择合适的拷贝方式,可以极大地提升程序的健壮性和可维护性。
希望通过本篇文章,你对 Java 的对象复制有了更深入的理解!如有任何问题,欢迎交流讨论。