Java深拷贝和浅拷贝

是什么

  • 浅拷贝:通常来讲,一个对象使用Object.clone()方法属于浅拷贝,浅拷贝只拷贝基本类型和String类型的成员变量。它的特点是,一个对象如果有引用类型的成员变量(String除外),浅拷贝只是拷贝这个成员变量的引用到新的对象,即两个对象中的这两个成员变量,共用一个内存地址。随之带来的问题是,一个对象改变了这个成员变量的值,另一个对象的该成员变量也随之修改。
  • 深拷贝:深拷贝则是给拷贝后的该引用变量开辟了一个新的内存空间,也就是该引用变量与拷贝前的引用变量的内存地址不一样了。 这样的话,修改不会影响到彼此。

需要明确的是,两种拷贝后两个对象是不相等的。

举例说明:

浅拷贝

首先,要使用clone方法需要实现Cloneable接口,并重写clone方法,并修改方法为public

@Data
@AllArgsConstructor
class Person implements Cloneable {
    private String name;
    private int age;
    private Dog dog;

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

@Data
@AllArgsConstructor
class Dog {
    private String color;
}

public class CopyTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person("Tom", 10, new Dog("black"));
        Person clone = (Person) person.clone();
        System.out.println("person == clone : " + (person == clone));
        
        System.out.println("===== clone对象修改自身属性 =====");
        clone.setName("Bob");
        clone.setAge(30);
        clone.getDog().setColor("white");

        System.out.println(person);
        System.out.println(clone);
    }
}
person == clone : false
===== clone对象修改自身属性 =====
Person(name=Tom, age=10, dog=Dog(color=white))
Person(name=Bob, age=30, dog=Dog(color=white))

这就是浅拷贝,clone对象修改了dogperson对象中的dog也被修改了,因为两个引用变量指向同一个内存地址。

如何实现深拷贝呢?

方法一:把引用类型的成员变量再clone一次。

@Data
@AllArgsConstructor
class Person implements Cloneable {
    private String name;
    private int age;
    private Dog dog;

    @Override
    public Object clone() throws CloneNotSupportedException {
        Person clone = (Person) super.clone();
        clone.setDog((Dog) clone.getDog().clone());
        return clone;
    }
}

这种方式,Dog也要实现Cloneable

方法二:参考网上的工具类。值得注意的是 Spring 和 Apache 的BeanUtils都是浅拷贝。

posted @ 2023-06-29 14:34  xfcoding  阅读(81)  评论(0编辑  收藏  举报