当前位置: 首页 > article >正文

【Java基础面试题041】Java中的深拷贝和浅拷贝有什么区别?

回答重点

深拷贝:深拷贝不仅复制对象本身,还递归复制对象中所有引用的对象。这样新对象与原对象完全独立,修改新对象不会影响到原对象。即包括基本类型和引用类型,堆内的引用对象也会复制一份

浅拷贝:浅拷贝只复制对象的引用,而不复制引用指向的实际对象,也就是说,浅拷贝创建一个新对象,但它的字段(若是对象类型)指向的是原对象中的相同内存地址

深拷贝创建的新对象与原对象完全独立,任何一个对象的修改都不会影响另一个。二修改浅拷贝对象中的引用类型的字段会影响要原对象,因为它们共享相同的引用

扩展知识

图示深浅拷贝

浅拷贝实现

常见实现方式是重写Object.clone()方法,默认方法这个方法只是对对象的字段进行字段拷贝,对于基本类型的字段会复制值,对于引用类型的字段则复制引用

重写Clone()的类需要实现Cloneable接口,否则抛出异常CloneNotSupportedException

public class ShallowCopyTest {
    public static void main(String[] args) throws CloneNotSupportedException{
        ShallowCopyTest test = new ShallowCopyTest();
        Person john = test.new Person("John", 25, new ArrayList<>(Arrays.asList("电玩", "旅游")));
        Person johnCopy = (Person) john.clone();
        System.out.println(john);
        System.out.println(johnCopy);
        System.out.println(john.hobbies == johnCopy.hobbies);
    }

    class Person implements Cloneable{
        String name;
        int age;
        List<String> hobbies;

        public Person(String name, int age, List<String> hobbies) {
            this.name = name;
            this.age = age;
            this.hobbies = hobbies;
        }

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

        @Override
        public String toString(){
            return name + "已经" + age + "岁了,喜欢" + hobbies.get(0) + " 和 " + hobbies.get(1);
        }
    }
}

深拷贝实现

深拷贝可以通过递归调用clone()方法手动实现,也可以通过序列化与反序列化实现。序列化方式简单易用,但性能相对较低,尤其是在深层嵌套对象或大对象的情况下。

  • 递归调用clone()实现
public class DeepCopyTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        DeepCopyTest test = new DeepCopyTest();
        People people = test.new People("Autism", 21, test.new Address("HeFei"));
        People clone = (People) people.clone();
        System.out.println(people.address == clone.address);
    }

    class People implements Cloneable{
        String name;
        int age;
        Address address;

        public People(String name, int age, Address address) {
            this.name = name;
            this.age = age;
            this.address = address;
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            People p = (People) super.clone(); // 先浅拷贝
            p.address = (Address) address.clone(); // 引用字段手动拷贝
            return p;
        }
    }
    class Address implements Cloneable{
        String city;
        public Address(String city){
            this.city = city;
        }
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
}

  • 序列化实现
public static Object deepCopy(Object object) {
    try {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(object);
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}


http://www.kler.cn/a/456970.html

相关文章:

  • JS中的鼠标事件和键盘事件基础
  • 工业以太网交换机怎么挑选?
  • 前端Python应用指南(六)构建RESTful API:使用Flask和Django实现用户认证与授权
  • AIA - APLIC之二
  • C 实现植物大战僵尸(四)
  • 如何检测PWA是否已经安装?
  • 解决tomcat双击startup.bat乱码的几种方法
  • 前端+后端之网站部署(Front End and Backend Website Deployment)
  • TCP Analysis Flags 之 TCP Out-Of-Order
  • C++的第一个程序
  • 1228java面经
  • Mybatis插件better-mybatis-generator的下载与使用
  • 为什么深度学习和神经网络要使用 GPU?
  • 数据标注的流程
  • C#中的属性索引器(Indexer)
  • JavaScript 箭头函数
  • 强化特种作业管理,筑牢安全生产防线
  • 【微信小程序】4|搜索框-历史搜索 | 我的咖啡店-综合实训
  • Numpy指南:解锁Python多维数组与矩阵运算(下)
  • LeetCode--排序算法(堆排序、归并排序、快速排序)
  • 防抖和节流的方法详解和CSS文本溢出小知识
  • 【学习总结|DAY025】JAVA-WEB基础
  • 代码随想录算法训练营第十六天-二叉树-513.找树左下角的值
  • python常用内建模块:struct
  • React(一)—— router/useRef/useState
  • 地理数据库Telepg面试内容整理-如何解决大规模地理数据导入时出现的性能瓶颈