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

问:介绍一下Java中的深克隆浅克隆?

在Java中,对象克隆主要有两种方式:浅克隆(Shallow Clone)和深克隆(Deep Clone)。

浅克隆(Shallow Clone)

浅克隆会创建一个新对象,这个新对象有着原始对象属性值的一份精确拷贝。如果属性是基本数据类型,拷贝的就是值本身;如果属性是引用类型,拷贝的是内存地址,因此如果原始对象改变了这些引用类型的属性,克隆对象也会受到影响。

实现浅克隆的步骤

  1. 实现Cloneable接口。
  2. 重写Object类的clone()方法。

示例代码

import java.io.Serializable;

class Address implements Serializable {
    private String city;

    public Address(String city) {
        this.city = city;
    }

    // Getter 和 Setter 省略
}

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();
    }

    // Getter 和 Setter 省略
}

public class ShallowCloneExample {
    public static void main(String[] args) {
        try {
            Address addr = new Address("Beijing");
            Person original = new Person("Alice", addr);

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

            System.out.println("Original Person: " + original.name + ", Address: " + original.address.city);
            System.out.println("Cloned Person: " + cloned.name + ", Address: " + cloned.address.city);

            // 修改原始对象的地址
            original.address.city = "Shanghai";

            // 验证克隆对象的地址是否也被修改
            System.out.println("After modification, Original Address: " + original.address.city);
            System.out.println("After modification, Cloned Address: " + cloned.address.city);

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

注意事项

  • 浅克隆只复制对象本身和包含的所有值类型的成员变量,而引用类型的成员变量仍然指向原来的对象。
  • 如果需要深克隆,则需要自定义克隆逻辑,确保所有引用类型的成员变量也被克隆。
深克隆(Deep Clone)

深克隆不仅复制对象本身,还复制对象所引用的所有对象,并创建新的内存地址。这样,原始对象和克隆对象之间就完全独立了。

实现深克隆的常用方法

  • 使用序列化(Serialization)和反序列化(Deserialization)。

示例代码(使用序列化实现深克隆):

import java.io.*;

// 假设Person和Address类如上定义,并实现了Serializable接口

public class DeepCloneExample {
    public static void main(String[] args) {
        try {
            Address addr = new Address("Beijing");
            Person original = new Person("Alice", addr);

            Person cloned = deepClone(original);

            System.out.println("Original Person: " + original.name + ", Address: " + original.address.city);
            System.out.println("Cloned Person: " + cloned.name + ", Address: " + cloned.address.city);

            // 修改原始对象的地址
            original.address.city = "Shanghai";

            // 验证克隆对象的地址是否也被修改
            System.out.println("After modification, Original Address: " + original.address.city);
            System.out.println("After modification, Cloned Address: " + cloned.address.city);

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static <T> T deepClone(T object) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(object);

        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);

        @SuppressWarnings("unchecked")
        T clonedObj = (T) ois.readObject();
        return clonedObj;
    }
}

注意事项

  • 序列化方式虽然可以实现深克隆,但会涉及到IO操作,可能会影响性能
对比总结

下面是关于深克隆和浅克隆差异的对比总结两者之间的主要区别:

浅克隆(Shallow Clone)深克隆(Deep Clone)
定义复制对象本身及其值类型属性,但复制引用类型属性时只复制引用地址,不复制引用的对象。复制对象本身及其所有类型的属性,包括值类型和引用类型。对于引用类型,会递归复制其引用的对象,生成完全独立的副本。
复制范围仅复制对象及其直接包含的值类型属性;引用类型属性仅复制引用地址。复制对象及其所有成员,包括所有嵌套的对象和集合,生成一个完全独立的副本。
内存分配为新对象重新分配内存,但引用类型属性仍然指向原对象的相同内存地址。为新对象及其所有成员重新分配内存,生成全新的对象层次结构。
对象独立性克隆后的对象在修改引用类型属性时,可能会影响原对象,因为两者共享相同的引用对象。克隆后的对象与原对象完全独立,修改任一对象都不会影响另一个。
实现方式在Java中,通过覆盖Object类的clone()方法实现,但只能处理值类型属性和简单引用类型;对于复杂引用类型,需要手动处理。需要自定义克隆逻辑,通常通过递归地复制对象及其所有成员来实现。在Java中,可能需要结合使用Serializable接口和序列化/反序列化机制来实现。
复杂性相对简单,因为只需处理对象的直接成员。较为复杂,需要处理对象及其所有嵌套对象的克隆逻辑。
性能通常较快,因为不需要复制引用对象。可能较慢,特别是当对象结构复杂且包含大量嵌套对象时,因为需要递归复制。
使用场景适用于对象结构简单,或者不需要完全独立副本的场景。适用于需要完全独立副本,以避免修改相互影响的场景。

通过这个对比,可以清晰地看到深克隆和浅克隆在定义、复制范围、内存分配、对象独立性、实现方式、复杂性和性能等方面的主要差异。这些差异使得它们适用于不同的场景和需求。


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

相关文章:

  • 【Docker容器】一、一文了解docker
  • Spring:bean的配置
  • 电脑长期不用,开不了机怎样解决
  • 27-压力测试
  • Hybird和WebView
  • SpringBoot3全面复习
  • MySQL之SUBSTRING 和 SUBSTRING_INDEX函数
  • 力扣134.加油站
  • mysql 数据区备份
  • 物联网架构之CDH集群部署
  • 软件架构的发展经历了从单体结构、垂直架构、SOA架构到微服务架构的过程剖析
  • Python中的if语句,让你轻松实现逻辑控制!!
  • <Godot>工厂游戏练习笔记一<2D网格地图>
  • 基于JSP技术的在线BLOG网系统
  • ROS 简单导航
  • E30.【C语言】练习:sizeof和strlen的习题集(B)
  • Oracle TDE和表空间中的数据量有关系吗?
  • CMake构建学习笔记7-freetype库的构建
  • 【pgAdmin4】创建/删除:数据库Database和数据库表Table
  • Python办公自动化 获取文本数据 支持多种类型文件
  • android MutableLiveData 赋值
  • 甲基化组学全流程生信分析教程
  • 链游开发教学
  • 项目配置在nacos配置中心进行管理
  • SK Hynix明年将开发基于96/128 GB DDR5的CXL 2.0内存解决方案
  • 深入理解Python中的装饰器链(Chaining Decorators)