JAVA对象引用拷贝、浅拷贝和深拷贝,原来是这么回事

本文详细解释了Java中对象引用拷贝、浅拷贝和深拷贝的概念,以及它们的区别,包括复制内容、对象独立性、修改影响和实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

一、什么是对象引用拷贝

在Java中,对象的引用拷贝是指将一个对象的引用赋值给另一个变量。通过引用拷贝,两个变量将指向同一个对象,它们共享同一块内存空间。当修改其中一个变量指向的对象时,另一个变量也会受到影响。

下面是一个简单的示例代码,演示了对象引用拷贝的概念:

public class ReferenceCopyExample {
    public static void main(String[] args) {
        // 创建一个Person对象
        Person person1 = new Person("Alice", 25);
        
        // 将person1的引用拷贝给person2
        Person person2 = person1;
        
        System.out.println("person1: " + person1);
        System.out.println("person2: " + person2);
        
        // 修改person1的属性
        person1.setName("Bob");
        person1.setAge(30);
        
        System.out.println("person1: " + person1);
        System.out.println("person2: " + person2);
    }
}

class Person {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    @Override
    public String toString() {
        return "Person[name=" + name + ", age=" + age + "]";
    }
}

在上述代码中,创建了一个Person对象person1,然后将其引用拷贝给person2。修改person1的属性后,打印person1person2的值,可以发现它们指向同一个对象,因此修改person1的属性后,person2的属性也会相应改变。

输出结果如下:

person1: Person[name=Alice, age=25]
person2: Person[name=Alice, age=25]
person1: Person[name=Bob, age=30]
person2: Person[name=Bob, age=30]

可以看到,通过引用拷贝,person1person2指向同一个Person对象,修改其中一个对象的属性会影响另一个对象。

在这里插入图片描述

二、什么是浅拷贝

在Java中,浅拷贝(Shallow Copy)是指创建一个新对象,并将原始对象中的所有字段的值复制到新对象中。浅拷贝只是简单地复制对象的字段值,如果对象中包含引用类型的字段,则新对象和原始对象会共享这些引用类型的字段。

浅拷贝是通过复制对象的引用来实现的,也就是说,新对象和原始对象指向了同一个内存地址。因此,如果修改了新对象的引用类型字段的值,原始对象的引用类型字段的值也会被修改,因为它们指向同一个对象。

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

使用Object类的clone()方法:Object类中的clone()方法可以复制一个对象,但它只复制对象的字段值,不复制引用类型字段指向的对象。因此,如果对象中包含引用类型字段,那么新对象和原始对象会共享这些引用类型的字段。

public class MyClass implements Cloneable {
    private int value;
    private MyObject obj;

    // 构造函数和其他方法

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

使用拷贝构造函数:通过定义一个构造函数,参数为原始对象,将原始对象中的字段值复制到新对象中。

public class MyClass {
    private int value;
    private MyObject obj;

    // 构造函数和其他方法

    public MyClass(MyClass original) {
        this.value = original.value;
        this.obj = original.obj;
    }
}

需要注意的是,浅拷贝只是复制对象的字段值,而不复制对象内部的引用类型字段的值。因此,如果需要实现深拷贝,就需要对引用类型字段进行递归拷贝,确保新对象和原始对象的引用类型字段指向不同的对象。

在这里插入图片描述

三、什么是深拷贝

在 Java 中,深拷贝(Deep Copy)是指创建一个新对象,将原始对象中的所有字段的值都复制到新对象中。深拷贝会递归复制对象的所有层级,包括对象的引用类型字段,确保新对象和原始对象完全独立相对地,浅拷贝(Shallow Copy)只是简单地复制对象的字段值,如果对象中包含引用类型的字段,那么新对象和原始对象会共享这些引用类型的字段。

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

实现 Cloneable口和覆写 clone() 方法:通过实现 Cloneable 接口来指明对象可以进行拷贝操作,并覆写 clone() 方法来实现深拷贝的逻辑。

public class MyClass implements Cloneable {
    private int value;
    private MyObject obj;

    // 构造函数和其他方法

    @Override
    protected Object clone() throws CloneNotSupportedException {
        MyClass newObj = (MyClass) super.clone();
        newObj.obj = (MyObject) obj.clone(); // 对引用类型字段也进行拷贝
        return newObj;
    }
}

使用序列化和反序列化:通过将对象序列化为字流,再将字节流反序列化为新对象来实现深拷贝。

public class MyClass implements Serializable {
    private int value;
    private MyObject obj;

    // 构造函数和其他方法

    public MyClass deepCopy() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this); // 序列化当前对象

        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (MyClass) ois.readObject(); // 反序列化生成新对象
    }
}

需要注意的是,为了现深拷贝,不仅仅需要拷贝对象本身,还需要拷贝对象内部的引用类型字段。因此,如果引用类型字段也需要支持深拷贝,那么该引用类型也需要实现 Cloneable 接口或者序列化接口,并在拷贝方法中进行递归拷。

在这里插入图片描述

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

在Java中,浅拷贝(ShallowCopy)和深拷贝(DeepCopy)是两种不同的对象拷贝方式,它们的主要区别如下:

  1. 复制的内容不同:
    • 浅拷贝只复制对象的字段值,不复制引用类型字段指向的对象。
    • 深拷贝会递归复制对象的所有层级,包括对象的引用类型字段。
  2. 对象的独立性不同:
    • 浅拷贝复制后的对象与原始对象共享相同的引用类型字段,即它们指向相同的对象。
    • 深拷贝复制后的对象与原始对象完全独立,它们的引用类型字段指向不同的对象。
  3. 对象修改的影响不同:
    • 浅拷贝中,如果修改新对象的引用类型字段的值,原始对象的相应字段也会被修改,因为它们指向同一个对象。
    • 深拷贝中,修改新对象的引用类型字段的值不会影响原始对象的相应字段,因为它们指向不同的对象。
  4. 实现方式不同:
    • 浅拷贝可以通过Object类的clone()方法、拷贝构造函数等方式实现。
    • 深拷贝需要对对象的引用类型字段进行递归拷贝,可以通过实现Cloneable接口和覆盖clone()方法、使用序列化和反序列化等方式实现。

总结来说,浅拷贝只复制对象的字段值,不复制引用类型字段指向的对象,而深拷贝会递归复制所有层级的对象,确保新对象和原始对象完全独立。因此,深拷贝相比浅拷贝更加安全,但也需要更多的资源和性能开销。选择使用哪种拷贝方式,需要根据具体的场景和需求来决定。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨荧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值