Java 深拷贝时集合对象未拷贝

引言

在Java编程中,我们经常需要对对象进行拷贝操作。拷贝操作可以分为浅拷贝和深拷贝两种。浅拷贝只复制对象的引用,而深拷贝则是创建一个全新的对象,将原对象的所有属性复制到新对象中。然而,在进行深拷贝时,我们可能会遇到集合对象未被正确拷贝的问题。本文将介绍这个问题的原因以及如何解决。

问题描述

当我们进行深拷贝操作时,使用的是对象的clone()方法或者序列化方式。在大多数情况下,这些方法可以正确地拷贝对象的属性。然而,当对象中包含集合对象时,拷贝的结果可能会出现问题。

import java.util.ArrayList;
import java.util.List;

public class Person implements Cloneable {
    private String name;
    private List<String> hobbies;

    public Person(String name, List<String> hobbies) {
        this.name = name;
        this.hobbies = hobbies;
    }

    public String getName() {
        return name;
    }

    public List<String> getHobbies() {
        return hobbies;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        List<String> hobbies = new ArrayList<>();
        hobbies.add("reading");
        hobbies.add("swimming");
        Person person1 = new Person("Alice", hobbies);
        Person person2 = (Person) person1.clone();
        
        // 修改person2的hobbies
        person2.getHobbies().add("dancing");
        
        System.out.println(person1.getHobbies()); // [reading, swimming, dancing]
        System.out.println(person2.getHobbies()); // [reading, swimming, dancing]
    }
}

上述代码中,我们创建了一个Person类,包含了一个hobbies属性,它是一个List集合。在main方法中,我们创建了一个person1对象,并将其hobbies属性设置为[reading, swimming]。然后,我们使用clone()方法创建了一个person2对象。

接着,我们修改了person2对象的hobbies属性,向其中添加了一个新的元素dancing。然而,我们发现person1hobbies属性也被修改了,结果变成了[reading, swimming, dancing]。这不是我们所期望的拷贝结果。

深拷贝中集合对象未被拷贝的原因

上述问题的原因在于,集合对象的拷贝仅仅是拷贝了它的引用,而没有创建一个新的集合对象。因此,当我们修改其中一个集合对象时,另一个集合对象也会被修改。

在上述代码中,person2hobbies属性实际上引用了和person1相同的ArrayList对象。因此,当我们向person2hobbies中添加元素时,实际上是修改了ArrayList对象本身,而不是创建一个新的对象。

解决方案

要解决上述问题,我们需要在深拷贝过程中,对集合对象也进行拷贝操作。下面是一种解决方案:

import java.util.ArrayList;
import java.util.List;

public class Person implements Cloneable {
    private String name;
    private List<String> hobbies;

    public Person(String name, List<String> hobbies) {
        this.name = name;
        this.hobbies = new ArrayList<>(hobbies);
    }

    public String getName() {
        return name;
    }

    public List<String> getHobbies() {
        return new ArrayList<>(hobbies);
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person clone = (Person) super.clone();
        clone.hobbies = new ArrayList<>(this.hobbies);
        return clone;
    }
}

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        List<String> hobbies = new ArrayList<>();
        hobbies.add("reading");
        hobbies.add("swimming");
        Person person1 = new Person("Alice", hobbies);
        Person person2 = (Person) person1.clone();
        
        // 修改person2的hobbies
        person2.getHobbies().add("dancing");
        
        System.out.println(person1.get