🎬 HoRain云小助手个人主页

 🔥 个人专栏: 《Linux 系列教程》《c语言教程

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

专栏介绍

专栏名称

专栏介绍

《C语言》

本专栏主要撰写C干货内容和编程技巧,让大家从底层了解C,把更多的知识由抽象到简单通俗易懂。

《网络协议》

本专栏主要是注重从底层来给大家一步步剖析网络协议的奥秘,一起解密网络协议在运行中协议的基本运行机制!

《docker容器精解篇》

全面深入解析 docker 容器,从基础到进阶,涵盖原理、操作、实践案例,助您精通 docker。

《linux系列》

本专栏主要撰写Linux干货内容,从基础到进阶,知识由抽象到简单通俗易懂,帮你从新手小白到扫地僧。

《python 系列》

本专栏着重撰写Python相关的干货内容与编程技巧,助力大家从底层去认识Python,将更多复杂的知识由抽象转化为简单易懂的内容。

《试题库》

本专栏主要是发布一些考试和练习题库(涵盖软考、HCIE、HRCE、CCNA等)

目录

⛳️ 推荐

专栏介绍

💻 实现方式详解

实现浅拷贝

实现深拷贝

💡 如何选择与注意事项


img

在Java中,实现对象的拷贝主要分为浅拷贝和深拷贝两种方式,它们的主要区别在于对对象内部引用类型字段的处理方式不同。下面是一个详细的对比表格,帮助你快速理解它们的核心差异。

特性

浅拷贝 (Shallow Copy)

深拷贝 (Deep Copy)

核心区别

复制对象本身,但对于引用类型字段,只复制其内存地址。

递归地复制对象及其所有引用类型字段指向的实际对象,直到所有依赖对象都被复制。

对象独立性

拷贝对象与原对象中的引用类型字段仍指向同一对象,修改会相互影响。

拷贝对象与原对象完全独立,互不影响。

性能与开销

创建速度快,内存开销小。

创建速度相对较慢,内存开销较大。

实现复杂度

简单。

复杂,需要递归处理所有引用对象。

💻 实现方式详解

实现浅拷贝

在Java中实现浅拷贝,主要依赖于让类实现 Cloneable接口并重写 Object类的 clone()方法。

  1. 实现Cloneable接口:这是一个标记接口,用于告知JVM该类支持克隆。

  2. 重写clone()方法:在方法内部调用 super.clone()Object类的 clone()方法本身会实现按位复制,从而创建新对象。

class Person implements Cloneable {
    private String name;
    private Address address; // 引用类型字段

    // ... 构造方法、getter、setter

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 调用super.clone()实现浅拷贝
        return super.clone();
    }
}

在上例中,对 Person对象进行浅拷贝后,新 Person对象的 address字段和原对象指向的是同一个 Address对象。

实现深拷贝

实现深拷贝需要确保所有引用类型字段也被独立复制。以下是几种常见方法:

  1. 通过 clone()方法递归实现

    这是最直接的方式,但要求所有包含的引用类型字段对应的类也必须正确实现 Cloneable接口和 clone()方法。

    class Address implements Cloneable {
        private String city;
        // ... 构造方法、getter、setter
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone(); // Address类自身的浅拷贝即可
        }
    }
    
    class Person implements Cloneable {
        private String name;
        private Address address;
    
        // ... 构造方法、getter、setter
        @Override
        protected Object clone() throws CloneNotSupportedException {
            Person cloned = (Person) super.clone();
            // 关键步骤:对address字段也调用其clone方法,进行深拷贝
            cloned.address = (Address) this.address.clone();
            return cloned;
        }
    }
  2. 通过序列化实现

    如果对象图(所有相关联的对象)都实现了 java.io.Serializable接口,可以利用序列化机制轻松实现深拷贝。这种方式无需手动处理复杂的嵌套关系。

    import java.io.*;
    
    public class SerializationUtils {
        public static <T extends Serializable> T deepCopy(T obj) throws Exception {
            // 将对象写入字节流
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            oos.close();
    
            // 从字节流中读回新对象
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (T) ois.readObject();
        }
    }
    
    // 使用:确保Person和Address都实现了Serializable接口
    Person original = new Person("Alice", new Address("Beijing"));
    Person deepCopy = SerializationUtils.deepCopy(original);

    这种方法的优点是简单,但性能较低,且所有涉及的对象都必须可序列化。

  3. 通过复制构造方法或工厂方法

    你也可以通过编写自定义的代码来逐一复制字段,例如为类添加一个接受自身类型参数的构造方法(复制构造方法)。

    class Address {
        private String city;
        public Address(Address other) {
            this.city = other.city; // 对于String等不可变对象,直接赋值是安全的
        }
    }
    
    class Person {
        private String name;
        private Address address;
        public Person(Person other) {
            this.name = other.name;
            this.address = new Address(other.address); // 为address创建新对象
        }
    }

💡 如何选择与注意事项

  • 性能与简单性:如果对性能要求高,且对象结构不复杂,优先选择通过 clone()递归实现。如果追求实现简单,且对象图都是可序列化的,序列化是不错的选择。

  • 数组的拷贝:Java数组本身实现了 Cloneable接口,但 Arrays.copyOf()和方法 clone()对对象数组进行的是浅拷贝。如需深拷贝对象数组,需要遍历数组并对每个元素实施深拷贝。

  • 不可变对象:如果类中包含的引用类型字段是不可变对象(如 String),由于它们无法被修改,使用浅拷贝也是安全的,因为不存在意外修改的风险。

希望这份详细的解释能帮助你彻底理解Java中的深拷贝与浅拷贝。如果你有特定的对象结构需要讨论,我可以提供更具体的实现建议。

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐