Java深拷贝和浅拷贝的实现方法

在Java中,对象的拷贝是一个常见的操作。有时候,我们需要创建一个新的对象,该对象的属性与原对象相同,但是两个对象是独立的,互不影响。这就引出了深拷贝和浅拷贝的概念。本文将介绍深拷贝和浅拷贝的概念,并提供了几种实现方法。

深拷贝与浅拷贝的概念

深拷贝(Deep Copy)是指将一个对象复制到另一个对象时,不仅复制对象本身,还要复制对象所引用的其他对象。这意味着在深拷贝中,如果原对象的属性是引用类型,那么拷贝出来的对象会拥有一个新的属性对象,而不是引用原对象的属性。

浅拷贝(Shallow Copy)是指将一个对象复制到另一个对象时,只复制对象本身,不复制对象所引用的其他对象。这意味着在浅拷贝中,如果原对象的属性是引用类型,那么拷贝出来的对象将引用原对象的属性。

代码示例

我们先定义一个示例类Person,它包含了一个引用类型的属性address

public class Person {
    private String name;
    private Address address;

    public Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }
}

public class Address {
    private String street;
    private String city;

    public Address(String street, String city) {
        this.street = street;
        this.city = city;
    }

    public String getStreet() {
        return street;
    }

    public String getCity() {
        return city;
    }
}

我们将使用这个示例类来演示深拷贝和浅拷贝的实现方法。

1. 通过重写clone()方法实现浅拷贝

Java中的Object类提供了clone()方法,我们可以通过重写该方法来实现浅拷贝。在重写clone()方法时,需要注意以下几点:

  • clone()方法的可见性设置为public
  • 返回类型应该是类本身或者其父类(即Object);
  • clone()方法中,调用super.clone()获取拷贝对象,并进行类型转换。

下面是通过重写clone()方法实现浅拷贝的示例代码:

public class Person implements Cloneable {
    // ...

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

然后,我们可以使用该方法进行浅拷贝:

Person person = new Person("Alice", new Address("123 Main St", "City"));
Person clone = person.clone();

System.out.println(clone.getName());  // 输出:Alice
System.out.println(clone.getAddress().getStreet());  // 输出:123 Main St

person.getAddress().setStreet("456 Main St");

System.out.println(clone.getAddress().getStreet());  // 输出:456 Main St

2. 通过拷贝构造函数实现浅拷贝

另一种实现浅拷贝的方式是使用拷贝构造函数。拷贝构造函数是一个构造函数,它的参数是同类型的对象,用于将参数对象的属性值复制到新对象中。

下面是通过拷贝构造函数实现浅拷贝的示例代码:

public class Person {
    // ...

    public Person(Person person) {
        this.name = person.name;
        this.address = person.address;
    }
}

然后,我们可以使用该构造函数进行浅拷贝:

Person person = new Person("Alice", new Address("123 Main St", "City"));
Person clone = new Person(person);

System.out.println(clone.getName());  // 输出:Alice
System.out.println(clone.getAddress().getStreet());  // 输出:123 Main St

person.getAddress().setStreet("456 Main St");

System.out.println(clone.getAddress().getStreet());  // 输出:456 Main St