关于浅拷贝和深拷贝

一、什么是拷贝?

先看下接口说明

/**
 * Creates and returns a copy of this object.  The precise meaning
 * of "copy" may depend on the class of the object. The general
 * intent is that, for any object {@code x}, the expression:
 * @see java.lang.Cloneable
 */
@IntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;

第一句话“Creates and returns a copy of this object.”就说明了,拷贝即创建一个该对象的副本。

二、浅拷贝和深拷贝

还是看接口说明

/** By convention, the object returned by this method should be independent
 * of this object (which is being cloned).  To achieve this independence,
 * it may be necessary to modify one or more fields of the object returned
 * by {@code super.clone} before returning it.  Typically, this means
 * copying any mutable objects that comprise the internal "deep structure"
 * of the object being cloned and replacing the references to these
 * objects with references to the copies.  If a class contains only
 * primitive fields or references to immutable objects, then it is usually
 * the case that no fields in the object returned by {@code super.clone}
 * need to be modified.
 */

大致意思是,拷贝的对象是独立的,如果包含深层结构(包含对象属性),那么这些引用的对象不会变,即深层结构需要单独处理

浅拷贝

用代码验证一下浅拷贝

/**
 * 铲屎官
 */
class CatOwner implements Cloneable {
    private String name;

    public String getName() {
        return name;
    }

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

    public Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();
        return obj;
    }
}

/**
 * 肥猫
 */
class FatCat implements Cloneable {
    private String name;

    private CatOwner catOwner;

    public String getName() {
        return name;
    }

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

    public CatOwner getCatOwner() {
        return catOwner;
    }

    public void setCatOwner(CatOwner catOwner) {
        this.catOwner = catOwner;
    }

    public Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();
        return obj;
    }
}

测试一下

public static void main(String[] args) throws CloneNotSupportedException {
     // 创建一个铲屎官Alex
     CatOwner Alex = new CatOwner();
     Alex.setName("Alex");
     // 拷贝一个Alex叫Rosie
     CatOwner Rosie = (CatOwner) Alex.clone();
     // 打印Alex的名称以及地址
     System.out.println(Alex.getName() + "::" + Alex);
     // 打印Rosie的名称以及地址
     System.out.println(Rosie.getName() + "::" + Rosie);
     // Alex和Rosie之间的类型比较和内容比较
     System.out.println(Alex + "::" + Rosie + "::"
             + Alex.getClass().equals(Rosie.getClass()) + "::" + Alex.equals(Rosie));

     Rosie.setName("Rosie");

     // 创建一个靓仔
     FatCat 靓仔 = new FatCat();
     靓仔.setName("靓仔");
     // 设置Rosie为靓仔的铲屎官
     靓仔.setCatOwner(Rosie);
     // 靓仔拷贝出一个扑街仔
     FatCat 扑街仔 = (FatCat) 靓仔.clone();
     // 打印靓仔的姓名,靓仔的铲屎官姓名,靓仔的地址,靓仔的铲屎官的地址
     System.out.println(靓仔.getName() + "::" + 靓仔.getCatOwner().getName()
             + "::" + 靓仔 + "::" + 靓仔.getCatOwner());
     // 打印扑街仔的姓名,扑街仔的铲屎官姓名,扑街仔的地址,扑街仔的铲屎官的地址
     System.out.println(扑街仔.getName() + "::" + 扑街仔.getCatOwner().getName()
             + "::" + 扑街仔 + "::" + 扑街仔.getCatOwner());
 }

输出结果

// 这是创建的Alex
Alex::xxx.CatOwner@6f496d9f
// 这是拷贝Alex的Rosie
Alex::xxx.CatOwner@723279cf
// 类型相同(都是铲屎官),地址不同(两个铲屎官)
xxx.CatOwner@6f496d9f::xxx.CatOwner@723279cf::true::false
// 靓仔和铲屎官Rosie
靓仔::Rosie::xxx.FatCat@1b2c6ec2::xxx.CatOwner@723279cf
// 扑街仔和Rosie,扑街仔是从靓仔拷贝来的,但是保留了铲屎官Rosie的信息,这就是浅拷贝
靓仔::Rosie::xxx.FatCat@4edde6e5::xxx.CatOwner@723279cf

深拷贝

深拷贝需要将靓仔的拷贝方法调整一下,如下:

/**
 * 肥猫
 */
class FatCat implements Cloneable {
    private String name;

    private CatOwner catOwner;

    public String getName() {
        return name;
    }

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

    public CatOwner getCatOwner() {
        return catOwner;
    }

    public void setCatOwner(CatOwner catOwner) {
        this.catOwner = catOwner;
    }

    public FatCat clone() throws CloneNotSupportedException {
        FatCat cat = (FatCat) super.clone();
        // 按照接口说明里,对深层结构做单独处理
        cat.setCatOwner((CatOwner) catOwner.clone());
        return cat;
    }
}

测试代码不变,输出结果如下

靓仔::Rosie::xxx.FatCat@9807454::xxx.CatOwner@723279cf
// @723279cf是Rosie,这里扑街仔的铲屎官已经不是Rosie了
靓仔::Rosie::xxx.FatCat@3d494fbf::xxx.CatOwner@1ddc4ec2

三、结论

浅拷贝:被拷贝的对象中,如果是基本数据类型,则是值传递,如果是引用数据类型,则是引用传递。
深拷贝:被拷贝的对象中,如果是基本数据类型,则是值传递,如果是引用数据类型,则会创建一个新的引用数据类型。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值