JAVA引用传递、浅拷贝、深拷贝

本文深入探讨Java中对象拷贝的概念,通过具体示例解释浅拷贝与深拷贝的区别,包括引用传递、对象复制及序列化实现深拷贝的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

测试类:

Player类,包含name  level  和  weapon   三个成员


public class Player implements Cloneable {

    private static final long serialVersionUID = -75L;

    private String name;
    private int level;
    private Weapon weapon;

    public Player(){
        name = "sam";
        level = 10;
        weapon = new Weapon();
    }

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public String getName() {
        return name;
    }

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

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public Weapon getWeapon() {
        return weapon;
    }

    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }

    @Override
    public String toString() {
        return "Player{" +
                "name='" + name + '\'' +
                ", level=" + level +
                ", weapon=" + weapon.getName() +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Player o = (Player) super.clone();
        return o;
    }
}

 Weapon:包含 name 一个成员


public class Weapon implements Cloneable {

    private String name;

    public Weapon(String name) {
        this.name = name;
    }

    public Weapon() {
        this.name = "AK74";
    }

    public String getName() {
        return name;
    }

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

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

1.  直接赋值,引用传递,C2 = C1 ,不会为复制过去的实例分配空间,C2这个引用直接指向C1的实例,C1中有成员改变,C2也同样改变,很好理解。

这里r1赋值给r2,之后改变r1的成员,再次打印r2

        Player r1 = new Player();
        Player r2 = r1;

        r1.setName("tom");
        r1.setLevel(20);
        r1.getWeapon().setName("HK416");

        System.out.println(r2);

输出结果:可见r2的值已经随着r1更新。 

 

2.  浅拷贝,使用Object.clone()方法 ,C1复制到新实例中(堆上分配空间),C2指向这个新实例。

复制的过程中:如果字段是值类型的,那么对该字段执行复制。如果该字段是引用类型的话,则复制引用但不复制引用的对象。

首先Player和Weapon都已实现Cloneable接口的clone方法,执行clone,之后改变r1的成员,再次打印r2内容

 
        Player r1 = new Player();
        Player r2 = (Player) r1.clone();

        r1.setName("tom");
        r1.setLevel(20);
        r1.getWeapon().setName("HK416");

        System.out.println(r2);

输出结果:r2中,字段为值类型的部分则被复制成功,随着r1更新,并未变化。但weapon字段却更新为HK416了,说明r2中的weapon还是指向了r1的weapon

 
3.  深拷贝,同样使用Object.clone()方法 ,复制引用并同时复制引用的对象
 
重构Player中的clone方法,将引用类型成员也clone过去。
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Player o = (Player) super.clone();
        o.weapon = (Weapon) weapon.clone();
        return o;
    }

 输出结果:可见此时r2完全未受到r1成员变更的影响,通俗的理解,r2现在完全与r1脱离了。

4. 深拷贝的另一种实现:实现 Serializable接口,序列化,写入文件再读出,这个很好理解,读出来,是一个新的实例了,肯定是深拷贝。不再赘述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值