Java基础系列:浅克隆和深克隆

博客主要介绍了浅拷贝和深拷贝的相关知识。通过对比引用拷贝、浅拷贝和深拷贝在堆空间分配上的不同,指出引用拷贝共用堆空间,浅拷贝只为一级属性开辟新堆空间,共用引用类堆空间,深拷贝则为所有属性开辟新堆空间。

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

1 实体

1.0 浅拷贝实体

package com.company.common;

import java.io.Serializable;

/**
 * 用户信息实体
 * @author xindaqi
 * @since 2020-12-19
 */

public class UserInformationEntity implements Serializable, Cloneable {

//    private static final long serialVersionUID = 1547123013328323240L;

    public String nickname;

    private String address;

    private FamilyInformationEntity familyInformationEntity;

    public FamilyInformationEntity getFamilyInformationEntity() {
        return familyInformationEntity;
    }

    public void setFamilyInformationEntity(FamilyInformationEntity familyInformationEntity) {
        this.familyInformationEntity = familyInformationEntity;
    }

    public UserInformationEntity() {}

    public UserInformationEntity(String nickname, String address) {
        this.nickname = nickname;
        this.address = address;
    }

    public UserInformationEntity(String nickname, String address, FamilyInformationEntity familyInformationEntity) {
        this.nickname = nickname;
        this.address = address;
        this.familyInformationEntity = familyInformationEntity;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Object object = super.clone();
        return object;
    }
}

1.2 深拷贝实体

package com.company.common;

/**
 * 深拷贝对象
 * @author xindaqi
 * @since 2020-12-20
 */

public class UserInformationDeepEntity implements  Cloneable {

    public String nickname;

    private String address;

    private FamilyInformationEntity familyInformationEntity;

    public FamilyInformationEntity getFamilyInformationEntity() {
        return familyInformationEntity;
    }

    public void setFamilyInformationEntity(FamilyInformationEntity familyInformationEntity) {
        this.familyInformationEntity = familyInformationEntity;
    }

    public UserInformationDeepEntity() {}

    public UserInformationDeepEntity(String nickname, String address) {
        this.nickname = nickname;
        this.address = address;
    }

    public UserInformationDeepEntity(String nickname, String address, FamilyInformationEntity familyInformationEntity) {
        this.nickname = nickname;
        this.address = address;
        this.familyInformationEntity = familyInformationEntity;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        // 获取User对象
        UserInformationDeepEntity userInformationDeepEntity = (UserInformationDeepEntity) super.clone();
        /**
         * Family对象拷贝至User的Family对象
         * 在新开辟的堆空间,重新设置Family对象的值
         */
        userInformationDeepEntity.setFamilyInformationEntity((FamilyInformationEntity) userInformationDeepEntity.getFamilyInformationEntity().clone());
        return userInformationDeepEntity;
    }
}

1.3 引用实体

package com.company.common;

/**
 * 家庭信息实体
 * @author xindaqi
 * @since 2020-12-20
 */

public class FamilyInformationEntity implements Cloneable {

    private String address;

    private Integer memberCount;

    public FamilyInformationEntity() {}

    public FamilyInformationEntity(String address, Integer memberCount) {
        this.address = address;
        this.memberCount = memberCount;
    }


    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Integer getMemberCount() {
        return memberCount;
    }

    public void setMemberCount(Integer memberCount) {
        this.memberCount = memberCount;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Object object = super.clone();
        return object;
    }
}

2 引用拷贝(克隆)

package com.company.clone;

import com.company.common.UserInformationEntity;

/**
 * 拷贝
 * @author xindaqi
 * @since 2020-12-20
 */

public class ShallowClone {

    public static void main(String[] args) {
        UserInformationEntity userInformationEntity = new UserInformationEntity("xiaoxiao", "黑龙江");
        UserInformationEntity referenceObject = userInformationEntity;
        System.out.println("原对象: " + userInformationEntity);
        System.out.println("引用对象:" + referenceObject);
        try {
            UserInformationEntity copyObject = (UserInformationEntity) userInformationEntity.clone();
            System.out.println("拷贝对象:" + copyObject);
        } catch(Exception e) {
            e.printStackTrace();
        }

    }
}

  • 结果
原对象: com.company.common.UserInformationEntity@6e0be858
引用对象:com.company.common.UserInformationEntity@6e0be858
拷贝对象:com.company.common.UserInformationEntity@61bbe9ba
  • 堆结果
    在这里插入图片描述
图1.0 引用拷贝与对象拷贝结果

由图1.0可知,原对象和引用拷贝对象的地址相同,均指向同一个地址@512,原对象和拷贝对象的地址不同,说明,拷贝对象新建了一个新的对象,开辟新型的堆内存@513。

3 浅拷贝(克隆)

只为第一级属性开辟堆空间,共用引用类(嵌套类)属性,即新建的对象只限于第一层属性,不会穿透其他对象。

package com.company.clone;

import com.company.common.FamilyInformationEntity;
import com.company.common.UserInformationEntity;

/**
 * 浅克隆
 * @author xindaqi
 * @since 2020-12-20
 */

public class ShallowClone {

    public static void main(String[] args) {
        FamilyInformationEntity familyInformationEntity = new FamilyInformationEntity("黑龙江", 3);
        UserInformationEntity userInformationEntity = new UserInformationEntity("xiaoxiao", "黑龙江", familyInformationEntity);
        System.out.println("原对象: " + userInformationEntity);
        try {
            UserInformationEntity shallowCopyObject = (UserInformationEntity) userInformationEntity.clone();
            System.out.println("浅拷贝对象:" + shallowCopyObject);
        } catch(Exception e) {
            e.printStackTrace();
        }

    }
}
  • 结果如图

在这里插入图片描述

图2.1 浅拷贝

由图2.1可知,User实体中包含Family实体(引用类)地址分配如下表,User类内的Famliy堆地址为511,而浅拷贝的对象shallow中的family对象地址仍为511,说明浅拷贝只为原对象第一级属性开辟了内存空间,与原对象共用引用的对象。

序号对象堆地址
1user508
2family511
3shallowCopyObject512

4 深拷贝(拷贝)

为所有属性开辟堆空间,即穿透所有引用的类。

package com.company.clone;

import com.company.common.FamilyInformationEntity;
import com.company.common.UserInformationDeepEntity;
import com.company.common.UserInformationEntity;

/**
 * 深拷贝
 * @author xindaqi
 * @since 2020-12-20
 */

public class DeepClone {

    public static void main(String[] args) {
        FamilyInformationEntity familyInformationEntity = new FamilyInformationEntity("黑龙江", 3);
        UserInformationDeepEntity userInformationDeepEntity = new UserInformationDeepEntity("xiaoxiao", "黑龙江", familyInformationEntity);
        System.out.println("原对象: " + userInformationDeepEntity);
        try {
            UserInformationDeepEntity deepCopyObject = (UserInformationDeepEntity) userInformationDeepEntity.clone();
            System.out.println("深拷贝对象:" + deepCopyObject);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

  • 结果

在这里插入图片描述

图3.1 深拷贝结果

由图3.1可知,User实体中包含Family实体(引用类)地址分配如下表,User类内的Famliy堆地址为511,深拷贝的对象deep中的family对象地址为516,说明深拷贝为所有的属性开辟堆空间。

5 小结

  • 引用:共用堆空间
  • 对象拷贝:开辟新的堆空间
  • 浅拷贝和浅拷贝均为对象拷贝,为属性开辟新的堆空间
  • 浅拷贝:只为一级属性开辟新的堆空间,共用应用的类所处的堆空间,不进行穿透开辟
  • 深拷贝:为所有属性开辟新的堆空间

【参考文献】
[1]https://blog.youkuaiyun.com/lcsy000/article/details/82782864
[2]https://blog.youkuaiyun.com/riemann_/article/details/87217229

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天然玩家

坚持才能做到极致

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值