引用拷贝、浅拷贝、深拷贝

在Java中,引用拷贝、浅拷贝和深拷贝的概念可以通过以下代码案例来说明:

引用拷贝(直接赋值)

案例:

public class Main {
    public static void main(String[] args) {
        // 创建一个Person对象
        Person original = new Person("Alice", 25);

        // 引用拷贝:直接将对象引用赋值给新的引用
        Person referenceCopy = original;

        // 修改原始对象的属性
        original.setName("Bob");

        // 输出结果
        System.out.println(original.getName()); // Bob
        System.out.println(referenceCopy.getName()); // Bob (因为两个引用指向同一个对象)
    }
}

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    // ... 其他getter和setter
}

在这个例子中,referenceCopyoriginal 的引用拷贝,它们指向相同的内存地址,因此当原始对象的属性发生改变时,通过引用拷贝得到的对象也会反映出这些变化。

浅拷贝

案例:

import java.util.Date;

public class Main {
    public static void main(String[] args) {
        // 创建一个包含嵌套对象的Person对象
        PersonWithAddress original = new PersonWithAddress("Alice", 25, new Address("1st Street"));

        // 浅拷贝:使用Cloneable接口实现浅拷贝
        PersonWithAddress shallowCopy = original.clone();

        // 修改原始对象内嵌对象的属性
        original.getAddress().setStreet("2nd Street");

        // 输出结果
        System.out.println(original.getAddress().getStreet()); // 2nd Street
        System.out.println(shallowCopy.getAddress().getStreet()); // 2nd Street (因为地址对象被共享)
    }
}

class PersonWithAddress implements Cloneable {
    private String name;
    private int age;
    private Address address;

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone(); // 这里进行的是浅拷贝
    }

    // ... getter和setter

    public Address getAddress() {
        return address;
    }
}

class Address {
    private String street;

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

    public void setStreet(String street) {
        this.street = street;
    }

    public String getStreet() {
        return street;
    }
}

在这个案例中,PersonWithAddress 类实现了 Cloneable 接口并调用了 super.clone() 方法来进行浅拷贝。虽然 shallowCopy 创建了一个新的 PersonWithAddress 对象,但其中的 address 属性仍然与 original 中的 address 引用相同,这意味着它们共享同一个内嵌的 Address 对象。因此,即使进行了浅拷贝,修改原始对象内嵌对象的属性仍会影响到拷贝后的对象。

深拷贝

案例:

import java.util.Date;
import java.io.Serializable;

public class Main {
    public static void main(String[] args) {
        // 创建一个包含嵌套对象的Person对象
        PersonWithSerializableAddress original = new PersonWithSerializableAddress("Alice", 25, new SerializableAddress("1st Street"));

        // 深拷贝:使用序列化和反序列化实现深拷贝
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(original);

            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            PersonWithSerializableAddress deepCopy = (PersonWithSerializableAddress) ois.readObject();

            // 修改原始对象内嵌对象的属性
            original.getAddress().setStreet("2nd Street");

            // 输出结果
            System.out.println(original.getAddress().getStreet()); // 2nd Street
            System.out.println(deepCopy.getAddress().getStreet()); // 1st Street (因为深拷贝后地址对象不共享)
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class PersonWithSerializableAddress {
    private String name;
    private int age;
    private SerializableAddress address;

    // 构造函数、getter和setter...

    public SerializableAddress getAddress() {
        return address;
    }
}

class SerializableAddress implements Serializable {
    private String street;

    public SerializableAddress(String street) {
        this.street = street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public String getStreet() {
        return street;
    }
}

在这个深拷贝的例子中,我们利用了Java的序列化和反序列化机制。通过将对象写入字节流再从字节流读取,可以实现深拷贝,确保所有嵌套的对象也都会被复制一份新的实例。因此,即使修改了原始对象内嵌对象的属性,也不会影响到深拷贝后的对象。

注意:实际开发中,如果要实现深拷贝,通常会重写 clone() 方法,并在其中手动处理嵌套对象的深拷贝,而不是简单地调用 super.clone()。另外,对于复杂的数据结构,可能需要设计更复杂的深拷贝逻辑,尤其是涉及循环引用或非序列化对象时。上述深拷贝的例子简化了许多细节,真实情况可能需要更多异常处理和其他策略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值