Java深拷贝和浅拷贝图解
在Java编程中,我们经常需要复制对象。然而,简单的复制并不总是满足我们的需求。有时候我们需要完全独立的对象,而不是只是对象的引用。这就需要我们了解深拷贝和浅拷贝的概念。
浅拷贝
浅拷贝是指创建一个新对象,然后将原始对象的字段值复制到新对象中。新对象和原始对象共享相同的内存地址,因此对字段值的改变会影响到两个对象。换句话说,浅拷贝只是复制了对象的引用,而不是对象本身。
下面是一个浅拷贝的示例代码:
public class Student implements Cloneable {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public static void main(String[] args) throws CloneNotSupportedException {
Student student1 = new Student("Alice", 18);
Student student2 = (Student) student1.clone();
System.out.println(student1.getName()); // Alice
System.out.println(student2.getName()); // Alice
student2.setName("Bob");
System.out.println(student1.getName()); // Alice
System.out.println(student2.getName()); // Bob
}
}
在上面的代码中,我们创建了一个Student
类,其中包含了一个name
和一个age
字段,以及相应的访问方法。在main
方法中,我们创建了一个名为student1
的对象,并将其拷贝给了student2
。然后我们改变了student2
的name
字段的值,发现student1
的name
字段并没有改变。
这是因为浅拷贝只复制了对象的引用,所以student1
和student2
引用的是同一个name
对象。因此,在改变student2
的name
字段值后,只影响了student2
而没有影响到student1
。
深拷贝
与浅拷贝不同,深拷贝是创建一个新对象,并将原始对象的所有字段复制到新对象中。新对象和原始对象不共享内存地址,因此对字段值的改变不会影响到原始对象。
有多种方式可以实现深拷贝,其中比较常用的是使用序列化和反序列化。
下面是一个使用序列化和反序列化实现深拷贝的示例代码:
import java.io.*;
public class Student implements Serializable {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
Student student1 = new Student("Alice", 18);
Student student2 = (Student) deepCopy(student1);
System.out.println(student1.getName()); // Alice
System.out.println(student2.getName()); // Alice
student2.setName("Bob");
System.out.println(student1.getName()); // Alice
System.out.println(student2.getName()); // Bob
}
public static Object deepCopy(Object object) throws IOException, ClassNotFoundException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(object);
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
return objectInputStream.readObject();
}
}
在上面的代码中,我们实现了Serializable
接口,并添加了一个deepCopy
方法用于深拷贝。在deepCopy
方法中,我们使用了序列化和反序列化的方式实现深拷贝。
与浅拷贝的示例相比,这次我们使用了deepCopy
方法对student1
进行拷贝,并将结果赋值给了student2
。然后我们改变了student2
的name
字段的值,发现student1
的name
字段并没有改变。
这是因为深拷贝创建了一个完