Java中的浅拷贝和深拷贝

在Java中,拷贝对象的方式可以分为浅拷贝和深拷贝两种。

浅拷贝

浅拷贝是指创建一个新对象,然后将原始对象的非静态字段值复制到新对象中,基本类型复制其值,引用类型则复制其引用(内存地址)。新旧对象仍然共享相同的引用对象,浅拷贝只复制对象本身,不会复制对象包含的引用对象。

可通过实现Cloneable接口并重写父类Object的clone方法来实现自定义的浅拷贝逻辑。Cloneable接口是一个标记接口,没有任何方法,仅用于表示该类支持clone操作。

class Address{
    String city;

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

    @Override
    public String toString() {
        return "Address{" +
                "city='" + city + '\'' +
                '}';
    }
}
class Person implements Cloneable {
    String name;
    Integer age;
    Address address;

    public Person(String name, Integer age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }

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

    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person("张三", 20, new Address("长沙"));
        Person clone = (Person) person.clone();
        // 修改克隆对象属性值
        clone.address.city = "深圳"; // 修改引用对象属性值
        clone.age = 18; // 修改基本类型值
        System.out.println(person);
        System.out.println(clone);
    }
}

通过测试新旧对象是两个对象,但仍然共享相同的引用对象。

深拷贝

深拷贝是指创建一个新对象,并复制原始对象及其包含的所有引用对象,深拷贝会复制整个对象引用链,使得新旧对象完全独立,互不影响。

实现深拷贝可以通过以下两种方法:

A、自定义深拷贝逻辑:通过手动创建新对象或调用引用对象的clone方法,确保对象及其引用对象的完全复制。

@Override
protected Object clone() throws CloneNotSupportedException {
    Person clone = (Person) super.clone();
    clone.address = new Address(this.address.city); // 手动创建复制Address对象
    return clone;
}
@Override
protected Object clone() throws CloneNotSupportedException {
    Person clone = (Person) super.clone();
    clone.address = (Address) this.address.clone(); // 调用引用对象的clone方法
    return clone;
}

B、使用序列化和反序列化:将对象序列化为字节流后再反序列化,可以得到一个全新的对象,其中包含的引用对象也会被复制。进行序列化的对象及其引用对象需要实现Serializable接口。

public class ShallowCopyTest {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Person person = new Person("张三", 20, new Address("长沙"));
        // 将对象写入字节流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(person);
        // 从字节流中读取对象实现深拷贝
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
        Person clone = (Person) ois.readObject();
        // 修改克隆对象属性值
        clone.address.city = "深圳"; // 修改引用对象属性值
        clone.age = 18; // 修改基本类型值
        System.out.println(person);
        System.out.println(clone);
    }
}

A和B方法都通过测试新旧对象是两个完全独立的对象。

需要注意在使用clone方法实现深拷贝时,被拷贝的类必须实现Cloneable接口并重写clone方法。而在使用序列化和反序列化实现深拷贝时,被拷贝的类及其引用对象都必须实现Serializable接口。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值