2025-11-16

在Java中,深复制和浅复制是对象复制的两种重要方式,它们的主要区别在于对引用类型字段的处理。

浅复制(Shallow Copy)

浅复制只复制对象本身,而不复制对象内部的引用类型字段所指向的对象。

特点:

基本类型字段:值复制

引用类型字段:复制引用(指向同一个对象)

实现方式:

1. 使用 clone() 方法

class Person implements Cloneable {

    private String name;

    private int age;

    private Address address; // 引用类型


    // 构造方法、getter/setter省略


    @Override

    protected Object clone() throws CloneNotSupportedException {

        return super.clone(); // 浅复制

    }

}

class Address {

    private String city;

    private String street;


    // 构造方法、getter/setter

}

2. 使用构造方法

class Person {

    private String name;

    private int age;

    private Address address;


    // 浅复制构造方法

    public Person(Person other) {

        this.name = other.name;

        this.age = other.age;

        this.address = other.address; // 共享同一个Address对象

    }

}

测试浅复制:

public class ShallowCopyDemo {

    public static void main(String[] args) throws CloneNotSupportedException {

        Address address = new Address("北京", "长安街");

        Person person1 = new Person("张三", 25, address);

        Person person2 = (Person) person1.clone();


        System.out.println(person1.getAddress() == person2.getAddress()); // true,同一个对象

        System.out.println(person1.getName() == person2.getName()); // true,字符串常量池


        // 修改原对象的引用类型字段

        person1.getAddress().setCity("上海");

        System.out.println(person2.getAddress().getCity()); // 输出"上海",受到影响

    }

}

深复制(Deep Copy)

深复制会复制对象及其所有引用类型字段指向的对象,创建完全独立的副本。

特点:

基本类型字段:值复制

引用类型字段:创建新的对象

实现方式:

1. 重写 clone() 方法实现深复制

class Person implements Cloneable {

    private String name;

    private int age;

    private Address address;


    // 深复制

    @Override

    protected Object clone() throws CloneNotSupportedException {

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

        cloned.address = (Address) address.clone(); // 复制Address对象

        return cloned;

    }

}

class Address implements Cloneable {

    private String city;

    private String street;


    @Override

    protected Object clone() throws CloneNotSupportedException {

        return super.clone();

    }

}

2. 使用序列化实现深复制

import java.io.*;

class DeepCopyUtil {

    @SuppressWarnings("unchecked")

    public static <T extends Serializable> T deepCopy(T object) {

        try {

            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            ObjectOutputStream oos = new ObjectOutputStream(baos);

            oos.writeObject(object);

            oos.close();


            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());

            ObjectInputStream ois = new ObjectInputStream(bais);

            return (T) ois.readObject();

        } catch (IOException | ClassNotFoundException e) {

            throw new RuntimeException("深复制失败", e);

        }

    }

}

// 需要实现Serializable接口

class Person implements Serializable {

    private String name;

    private int age;

    private Address address; // Address也需要实现Serializable


    // 使用序列化进行深复制

    public Person deepCopy() {

        return DeepCopyUtil.deepCopy(this);

    }

}

3. 使用复制构造方法实现深复制

class Person {

    private String name;

    private int age;

    private Address address;


    // 深复制构造方法

    public Person(Person other) {

        this.name = other.name;

        this.age = other.age;

        this.address = new Address(other.address); // 创建新的Address对象

    }

}

class Address {

    private String city;

    private String street;


    // 复制构造方法

    public Address(Address other) {

        this.city = other.city;

        this.street = other.street;

    }

}

测试深复制:

public class DeepCopyDemo {

    public static void main(String[] args) throws CloneNotSupportedException {

        Address address = new Address("北京", "长安街");

        Person person1 = new Person("张三", 25, address);

        Person person2 = (Person) person1.clone(); // 深复制


        System.out.println(person1.getAddress() == person2.getAddress()); // false,不同对象


        // 修改原对象的引用类型字段

        person1.getAddress().setCity("上海");

        System.out.println(person2.getAddress().getCity()); // 输出"北京",不受影响

    }

}

总结对比

特性浅复制深复制

基本类型字段值复制值复制

引用类型字段复制引用创建新对象

内存占用少多

性能快慢

对象独立性不独立完全独立

实现复杂度简单复杂

选择建议

使用浅复制:当引用类型字段是不可变的,或者你确实需要共享对象时

使用深复制:当需要完全独立的副本,避免意外的副作用时

考虑性能:深复制通常更耗时,特别是在对象图很深的情况下

在实际开发中,根据具体需求选择合适的复制策略非常重要。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容