Java中浅拷贝与深拷贝实例解析

 更新时间:2023年09月04日 08:29:46   作者:DS程序员  
这篇文章主要给大家介绍了关于Java中浅拷贝与深拷贝的相关资料,拷贝对象是java中经常会遇到的问题,文中通过代码示例介绍的非常详细,需要的朋友可以参考下

前言

在Java中,对象的拷贝有两种方式:浅拷贝和深拷贝。它们分别代表了不同的拷贝方式,拷贝出的新对象与原始对象之间存在一定的差异。本文将详细介绍浅拷贝和深拷贝的概念、特点和实现方式,并且通过实例进行解析。

一、浅拷贝 

浅拷贝是指在对一个对象进行拷贝时,只拷贝对象本身和其中的基本数据类型,而不拷贝对象内部的引用类型。因此,在浅拷贝的对象中,引用类型的变量指向的依旧是原始对象中的引用。

在Java中,实现浅拷贝可以使用Object类的clone()方法,或者手动重写类的clone()方法。下面是一个示例:

class Person implements Cloneable {
    private String name;
    private Address address;
    public Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Address {
    private String city;
    public Address(String city) {
        this.city = city;
    }
}
public class Test {
    public static void main(String[] args) throws Exception {
        Address address = new Address("Beijing");
        Person person1 = new Person("Tom", address);
        Person person2 = (Person) person1.clone();
        System.out.println(person1 == person2); // false
        System.out.println(person1.getAddress() == person2.getAddress()); // true
    }
}

在上述代码中,我们定义了一个Person类和Address类。Person类中包含一个引用类型的成员变量address。使用Object类的clone()方法进行拷贝,并且在Person类中实现了Cloneable接口,并重写了clone()方法,使得Person类可以进行拷贝。

在main函数中,我们创建了一个Person对象person1,其中包含一个Address对象。接着,我们使用person1的clone()方法创建了一个新的Person对象person2,并使用“==”判断person1和person2是否是同一对象。结果为false,证明两个对象是不同的。接下来,我们使用“==”判断person1和person2中的address是否是同一对象,结果为true,即两个对象的address成员变量指向的是同一个地址。

总的来说,浅拷贝只是将原始对象的引用类型成员变量复制到新的对象中,因此新对象中的引用类型成员变量与原始对象中的成员变量指向同一对象。如果原始对象中的引用类型成员变量发生变化,新对象中的引用类型成员变量也会随之变化。

二、深拷贝 

深拷贝是指在对一个对象进行拷贝时,不仅拷贝对象本身和其中的基本数据类型,同时也拷贝对象内部的引用类型。因此,在深拷贝的对象中,引用类型的变量指向的是全新的对象。

在Java中,实现深拷贝的方式比较多,可以使用对象的序列化、手动编写clone()方法等。下面是一个使用对象序列化来实现深拷贝的例子:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Test {
    public static void main(String[] args) throws Exception {
        Address address = new Address("Beijing");
        Person person1 = new Person("Tom", address);
        Person person2 = (Person) deepCopy(person1);
        System.out.println(person1 == person2); // false
        System.out.println(person1.getAddress() == person2.getAddress()); // false
    }
    private static Object deepCopy(Object obj) throws Exception {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    }
}
class Person implements Serializable {
    private String name;
    private Address address;
     public Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }
    public Address getAddress() {
        return address;
    }
}
class Address implements Serializable {
    private String city;
     public Address(String city) {
        this.city = city;
    }
}

在上述代码中,我们定义了一个Person类和Address类,并且让它们都实现了Serializable接口。在main函数中,我们创建了一个Person对象person1,其中包含一个Address对象。接着,我们使用deepCopy()方法创建了一个新的Person对象person2,并使用“==”判断person1和person2是否是同一对象。结果为false,证明两个对象是不同的。接下来,我们使用“==”判断person1和person2中的address是否是同一对象,结果为false,即两个对象的address成员变量指向的是不同的地址。

在上述代码中,我们使用了一个deepCopy()方法来实现对象的深拷贝。该方法使用对象的序列化和反序列化来实现深拷贝。首先,将原始对象序列化成字节数组,然后再将字节数组反序列化成新的对象。这样可以保证复制出的新对象与原始对象完全独立,不会相互影响。

总结: 

浅拷贝和深拷贝是Java中常用的两种对象拷贝方式。浅拷贝只会复制对象内部的基本数据类型和引用类型变量的引用,而深拷贝会将对象内部所有的基本类型和引用类型都复制一份。使用clone()方法和重写clone()方法可以实现浅拷贝,使用对象序列化或手动复制可以实现深拷贝。在实现对象拷贝时需要根据具体情况选择合适的拷贝方式,以保证复制出的新对象能够满足应用需求。

到此这篇关于Java中浅拷贝与深拷贝的文章就介绍到这了,更多相关Java浅拷贝与深拷贝内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 密码系统AES私钥RSA公钥的加解密示例

    密码系统AES私钥RSA公钥的加解密示例

    这篇文章主要为大家诠释并介绍了AES私钥RSA公钥的加解密系统示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-03-03
  • mybatis单笔批量保存实体数据的方法

    mybatis单笔批量保存实体数据的方法

    这篇文章主要介绍了mybatis单笔批量保存实体数据的相关知识,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-01-01
  • 使用SpringMVC接收文件流上传和表单参数

    使用SpringMVC接收文件流上传和表单参数

    这篇文章主要介绍了使用SpringMVC接收文件流上传和表单参数,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • Spring Data JPA实现持久化存储数据到数据库的示例代码

    Spring Data JPA实现持久化存储数据到数据库的示例代码

    Spring Data JPA是Spring基于JPA规范的基础上封装的⼀套 JPA 应⽤框架,可使开发者⽤极简的代码即可实现对数据库的访问和操作。本文我们来了解如何用Spring Data JPA框架实现数据持久化存储到数据库,感兴趣的可以了解一下
    2022-04-04
  • SpringMVC结合模板模式实现MyBatisPlus传递嵌套JSON数据

    SpringMVC结合模板模式实现MyBatisPlus传递嵌套JSON数据

    我们经常会遇到需要传递对象的场景,有时候,我们需要将一个对象的数据传递给另一个对象进行处理,但是又不希望直接暴露对象的内部结构和实现细节,所以本文给大家介绍了SpringMVC结合模板模式实现MyBatisPlus传递嵌套JSON数据,需要的朋友可以参考下
    2024-03-03
  • 深度剖析java中JDK动态代理机制

    深度剖析java中JDK动态代理机制

    本篇文章主要介绍了深度剖析java中JDK动态代理机制 ,动态代理避免了开发人员编写各个繁锁的静态代理类,只需简单地指定一组接口及目标类对象就能动态的获得代理对象。
    2017-04-04
  • java遍历properties文件操作指南

    java遍历properties文件操作指南

    在java项目开发过程中,使用properties文件作为配置基本上是必不可少的,有很多如系统配置信息,java如何遍历properties文件呢,本文将详细介绍,希望可以帮助到您
    2012-11-11
  • SpringBoot下载文件的正确解法方式

    SpringBoot下载文件的正确解法方式

    这篇文章主要给大家介绍了关于SpringBoot下载文件的正确解法方式,SpringBoot是一款流行的框架,用于开发Web应用程序,在使用SpringBoot构建Web应用程序时,可能需要实现文件下载的功能,需要的朋友可以参考下
    2023-08-08
  • Java框架Struts2实现图片上传功能

    Java框架Struts2实现图片上传功能

    这篇文章主要为大家详细介绍了Java框架Struts2实现图片上传功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • 在Java的Hibernate框架中对数据库数据进行查询操作

    在Java的Hibernate框架中对数据库数据进行查询操作

    这篇文章主要介绍了Java的Hibernate框架中对数据库数据进行查询操作的方法,Hibernate是Java的SSH三大web开发框架之一,需要的朋友可以参考下
    2015-12-12

最新评论