java如何实现深拷贝浅拷贝

java如何实现深拷贝浅拷贝

Java中实现深拷贝和浅拷贝的方法主要有使用clone()方法、通过构造函数拷贝、使用序列化、使用第三方库等。其中,使用clone()方法是一种简单且常见的方式。利用Java中的Cloneable接口和clone()方法,我们可以实现对象的浅拷贝。浅拷贝只复制对象的基本数据类型字段,而不复制引用对象,这意味着浅拷贝后的对象与原对象共享同一个引用对象。对于深拷贝,我们可以通过手动复制对象的所有字段,包括引用对象,或者使用序列化机制来实现。序列化机制将对象转化为字节流,再从字节流中恢复对象,从而实现深拷贝。接下来,我们将详细探讨这些方法。

一、使用clone()方法

1.1、浅拷贝

浅拷贝是指对象的字段是逐字段复制的,对于字段中引用的对象,只复制引用,不复制引用对象本身。实现浅拷贝的步骤如下:

class Person implements Cloneable {

String name;

int age;

public Person(String name, int age) {

this.name = name;

this.age = age;

}

@Override

protected Object clone() throws CloneNotSupportedException {

return super.clone();

}

@Override

public String toString() {

return "Person{name='" + name + "', age=" + age + "}";

}

}

public class Main {

public static void main(String[] args) {

try {

Person person1 = new Person("John", 25);

Person person2 = (Person) person1.clone();

System.out.println("Person 1: " + person1);

System.out.println("Person 2: " + person2);

person2.name = "Doe";

person2.age = 30;

System.out.println("After modifying person2:");

System.out.println("Person 1: " + person1);

System.out.println("Person 2: " + person2);

} catch (CloneNotSupportedException e) {

e.printStackTrace();

}

}

}

在这个例子中,修改person2的字段不会影响person1,因为它们的字段是独立的,但如果对象中包含引用类型,则引用类型的字段将共享。

1.2、深拷贝

深拷贝是指不仅复制对象的基本数据类型字段,还要递归复制对象中所有引用的对象,以确保拷贝的对象与原对象完全独立。实现深拷贝的方法如下:

class Address implements Cloneable {

String city;

public Address(String city) {

this.city = city;

}

@Override

protected Object clone() throws CloneNotSupportedException {

return super.clone();

}

@Override

public String toString() {

return "Address{city='" + city + "'}";

}

}

class Person implements Cloneable {

String name;

int age;

Address address;

public Person(String name, int age, Address address) {

this.name = name;

this.age = age;

this.address = address;

}

@Override

protected Object clone() throws CloneNotSupportedException {

Person cloned = (Person) super.clone();

cloned.address = (Address) address.clone();

return cloned;

}

@Override

public String toString() {

return "Person{name='" + name + "', age=" + age + ", address=" + address + "}";

}

}

public class Main {

public static void main(String[] args) {

try {

Address address = new Address("New York");

Person person1 = new Person("John", 25, address);

Person person2 = (Person) person1.clone();

System.out.println("Person 1: " + person1);

System.out.println("Person 2: " + person2);

person2.name = "Doe";

person2.age = 30;

person2.address.city = "Los Angeles";

System.out.println("After modifying person2:");

System.out.println("Person 1: " + person1);

System.out.println("Person 2: " + person2);

} catch (CloneNotSupportedException e) {

e.printStackTrace();

}

}

}

在这个例子中,修改person2address字段不会影响person1,因为address对象也被单独克隆了。

二、通过构造函数拷贝

2.1、浅拷贝

通过构造函数拷贝是一种手动实现浅拷贝的方法。它通过在新对象的构造函数中逐字段复制旧对象的字段来实现。

class Person {

String name;

int age;

public Person(String name, int age) {

this.name = name;

this.age = age;

}

public Person(Person other) {

this.name = other.name;

this.age = other.age;

}

@Override

public String toString() {

return "Person{name='" + name + "', age=" + age + "}";

}

}

public class Main {

public static void main(String[] args) {

Person person1 = new Person("John", 25);

Person person2 = new Person(person1);

System.out.println("Person 1: " + person1);

System.out.println("Person 2: " + person2);

person2.name = "Doe";

person2.age = 30;

System.out.println("After modifying person2:");

System.out.println("Person 1: " + person1);

System.out.println("Person 2: " + person2);

}

}

2.2、深拷贝

通过构造函数拷贝实现深拷贝,需要确保所有引用类型的字段也被单独复制。

class Address {

String city;

public Address(String city) {

this.city = city;

}

public Address(Address other) {

this.city = other.city;

}

@Override

public String toString() {

return "Address{city='" + city + "'}";

}

}

class Person {

String name;

int age;

Address address;

public Person(String name, int age, Address address) {

this.name = name;

this.age = age;

this.address = address;

}

public Person(Person other) {

this.name = other.name;

this.age = other.age;

this.address = new Address(other.address);

}

@Override

public String toString() {

return "Person{name='" + name + "', age=" + age + ", address=" + address + "}";

}

}

public class Main {

public static void main(String[] args) {

Address address = new Address("New York");

Person person1 = new Person("John", 25, address);

Person person2 = new Person(person1);

System.out.println("Person 1: " + person1);

System.out.println("Person 2: " + person2);

person2.name = "Doe";

person2.age = 30;

person2.address.city = "Los Angeles";

System.out.println("After modifying person2:");

System.out.println("Person 1: " + person1);

System.out.println("Person 2: " + person2);

}

}

三、使用序列化

3.1、深拷贝

使用序列化来实现深拷贝是非常可靠的一种方法,因为它会将对象的整个状态进行复制,包括所有引用的对象。

import java.io.*;

class Address implements Serializable {

String city;

public Address(String city) {

this.city = city;

}

@Override

public String toString() {

return "Address{city='" + city + "'}";

}

}

class Person implements Serializable {

String name;

int age;

Address address;

public Person(String name, int age, Address address) {

this.name = name;

this.age = age;

this.address = address;

}

@Override

public String toString() {

return "Person{name='" + name + "', age=" + age + ", address=" + address + "}";

}

public Person deepClone() {

try {

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);

objectOutputStream.writeObject(this);

ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);

return (Person) objectInputStream.readObject();

} catch (IOException | ClassNotFoundException e) {

e.printStackTrace();

return null;

}

}

}

public class Main {

public static void main(String[] args) {

Address address = new Address("New York");

Person person1 = new Person("John", 25, address);

Person person2 = person1.deepClone();

System.out.println("Person 1: " + person1);

System.out.println("Person 2: " + person2);

person2.name = "Doe";

person2.age = 30;

person2.address.city = "Los Angeles";

System.out.println("After modifying person2:");

System.out.println("Person 1: " + person1);

System.out.println("Person 2: " + person2);

}

}

四、使用第三方库

4.1、Apache Commons Lang

Apache Commons Lang提供了一个SerializationUtils类,可以方便地实现对象的深拷贝。

import org.apache.commons.lang3.SerializationUtils;

class Address implements Serializable {

String city;

public Address(String city) {

this.city = city;

}

@Override

public String toString() {

return "Address{city='" + city + "'}";

}

}

class Person implements Serializable {

String name;

int age;

Address address;

public Person(String name, int age, Address address) {

this.name = name;

this.age = age;

this.address = address;

}

@Override

public String toString() {

return "Person{name='" + name + "', age=" + age + ", address=" + address + "}";

}

}

public class Main {

public static void main(String[] args) {

Address address = new Address("New York");

Person person1 = new Person("John", 25, address);

Person person2 = SerializationUtils.clone(person1);

System.out.println("Person 1: " + person1);

System.out.println("Person 2: " + person2);

person2.name = "Doe";

person2.age = 30;

person2.address.city = "Los Angeles";

System.out.println("After modifying person2:");

System.out.println("Person 1: " + person1);

System.out.println("Person 2: " + person2);

}

}

通过这种方式,您不需要手动编写序列化和反序列化的代码,只需调用SerializationUtils.clone()方法即可实现对象的深拷贝。

总结

深拷贝和浅拷贝在Java中有多种实现方式,选择哪种方式取决于具体的需求和对象的复杂性。使用clone()方法适用于简单对象的浅拷贝和深拷贝,通过构造函数拷贝也能实现浅拷贝和深拷贝,但需要手动编写代码来复制对象的每个字段。使用序列化第三方库如Apache Commons Lang提供了更简洁和通用的深拷贝方法,适用于需要复制复杂对象的场景。无论使用哪种方法,都需要仔细考虑对象的结构和拷贝的深度,以确保拷贝后的对象能够正确地独立于原对象。

相关问答FAQs:

1. 什么是深拷贝和浅拷贝?

深拷贝和浅拷贝是在Java中用于复制对象的两种不同方式。浅拷贝仅仅复制对象的引用,而深拷贝会创建一个全新的对象,同时复制对象的所有属性。

2. 如何实现浅拷贝?

要实现浅拷贝,可以使用Java中的clone()方法。该方法会创建一个新的对象,并将原始对象的属性值复制到新对象中。但是需要注意的是,clone()方法只是复制了对象的引用,而不是对象本身。

3. 如何实现深拷贝?

要实现深拷贝,可以使用以下几种方式:

  • 使用序列化和反序列化:将对象序列化为字节流,然后再反序列化为一个新的对象。这种方法会创建一个全新的对象,并复制对象的所有属性。
  • 递归复制对象:遍历对象的每一个属性,如果属性是引用类型,则递归复制该属性。这样可以确保所有属性都是全新的对象。

无论是浅拷贝还是深拷贝,都要根据实际需求来选择适合的方法。如果只需要复制对象的引用,浅拷贝就可以满足需求;如果需要复制对象的所有属性,并确保每个属性都是全新的对象,就需要使用深拷贝。

原创文章,作者:Edit1,如若转载,请注明出处:https://docs.pingcode.com/baike/223052

(0)
Edit1Edit1
上一篇 2024年8月14日 上午3:14
下一篇 2024年8月14日 上午3:14
免费注册
电话联系

4008001024

微信咨询
微信咨询
返回顶部