专业的JAVA编程教程与资源

网站首页 > java教程 正文

5分钟掌握java对象的深拷贝和浅拷贝

temp10 2024-10-19 14:54:10 java教程 12 ℃ 0 评论

我们知道,在计算机内存中,每个对象都有一个地址,这个地址指向对象在内存中存储的位置。当我们使用变量引用一个对象时,实际上是将该对象的地址赋值给变量。因此,如果我们将一个对象复制到另一个变量中,实际上是将对象的地址复制到了这个变量中。这就涉及到我们今天要说的深拷贝和浅拷贝。

一、深拷贝和浅拷贝的区别

5分钟掌握java对象的深拷贝和浅拷贝

1、浅拷贝是指将一个对象复制到另一个变量中,但是只复制对象的地址,而不是对象本身。也就是说,原始对象和复制对象实际上是共享同一个内存地址的。

2、深拷贝是指将一个对象及其所有子对象都复制到另一个变量中,也就是说,它会创建一个全新的对象,并将原始对象中的所有属性或元素都复制到新的对象中。因此,如果我们修改复制对象中的属性或元素,原始对象中对应的属性或元素不会受到影响。

二、深拷贝和浅拷贝的实现

1、浅拷贝

实现对象拷贝的类,需要实现 Cloneable 接口,并覆写 clone() 方法。在Java中,我们常用的各种BeanUtils基本也都是浅拷贝的。

package com.demo;
public class CopyDemo {
    public static void main(String[] args) {
        Person person1 = new Person(new Car("鄂A123345"));
        Person person1Copy = person1.clone();
        System.out.println(person1.getCar() == person1Copy.getCar());
    }
}
class Car implements Cloneable{

    private final String carNo;

    public String getCarNo() {
        return carNo;
    }

    public Car(String carNo) {
        this.carNo = carNo;
    }
    @Override
    public Car clone() {
        try {
            return (Car) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}

class Person implements Cloneable {
    private Car car;
    public Car getCar() {
        return car;
    }
    public void setCar(Car car) {
        this.car = car;
    }
    public Person(Car car) {
        this.car = car;
    }
    @Override
    public Person clone() {
        try {
            Person person = (Person) super.clone();
            return person;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}

从输出结构就可以看出, person1 的克隆对象和 person1 使用的仍然是同一个 Car 对象。

2、深拷贝

实现Cloneable接口,重写clone()。在Object类中定义了一个clone方法,这个方法其实在不重写的情况下,其实也是浅拷贝的。如果想要实现深拷贝,就需要重写clone方法,而想要重写clone方法,就必须实现Cloneable,否则会报CloneNotSupportedException异常。

这里我们简单对 Person 类的 clone() 方法进行修改,连带着要把 Person 对象内部的 Car 对象一起复制。

@Override
public Person clone() {
try {
    Person person = (Person) super.clone();
    person.setCar(person.getCar().clone());
    return person;
} catch (CloneNotSupportedException e) {
    throw new AssertionError();
}

之后,再次在执行一下上面的main测试代码,就可以发现,这时候person1 的克隆对象和 person1 包含的 Car 对象已经是不同的了。

这种方式就能实现深拷贝,但是问题是如果我们在Person中有很多个对象,那么clone方法就写的很长,而且如果后面有修改,在Person中新增属性,这个地方也要改。

这时候可以借助序列化来实现深拷贝。先把对象序列化成流,再从流中反序列化成对象,这样就一定是新的对象了。

在实际开发过程中可以使用Apache Commons Lang中提供的SerializationUtils工具实现。我们先修改下上面的Person和Car类,使他们实现Serializable接口,否则是无法进行序列化的。

class Car implements Serializable
class Person implements Serializable

然后在需要拷贝的时候:

Person person1CopyNew= (Person)SerializationUtils.clone(person1);

以上详细讲解了java对象的深拷贝和浅拷贝的区别和应用,大家不妨动手试一试,了解一下java的高级用法,有问题可以在评论区一起交流!

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表