Java中的深拷贝与浅拷贝

clone 方法 与 Cloneable 接口

Ojbect类中的clone方法签名如下,native 指示其是一个本地方法(非Java实现)。需要注意的是该方法的访问修饰符为 protected,说明该方法只能在本包下或子类中去调用

protected native Object clone() throws CloneNotSupportedException;

标记接口:没有任何方法和字段的空接口,其仅用于说明该类支持某种特性/功能。Cloneable 接口 即是一个标记接口,其只表明所标记类的对象是可拷贝的,否则对该类的对象调用 clone 方法将会抛 CloneNotSupportedException异常

下述代码示例即对Dept类对象进行拷贝操作,该类实现了Cloneable接口,故可正常调用clone方法

浅拷贝

Object类中的clone方法的访问修饰符为 protected,只能在包内及其子类调用。故在我们自己类中一般通过重载的方式将该类的访问权限改为 public 来方便我们在类外使用它。
如下代码所示,我们重载Dept的clone方法,也仅仅是扩大了访问权限,其依然是调用Object中的clone方法去实现

package org.example.Cloneable;

import lombok.Data;
import java.util.Date;

/**
 * 部门类
 */
@Data
public class Dept implements Cloneable{
    private String deptName;    // 不可变对象属性
    private Integer totalNum;   // 不可变对象属性
    private int deptIdx;        // 非对象属性(基本类型属性)
    private Date createTime;    // 对象属性
    private Fence fence;       // 对象属性

    public Dept(String deptName, Integer totalNum, int deptIdx, Date createTime, Fence fence) {
        this.deptName = deptName;
        this.totalNum = totalNum;
        this.deptIdx = deptIdx;
        this.createTime = createTime;
        this.fence = fence;
    }

        @Override
        public Object clone(){
        Dept dept = null;
        try{
            dept = (Dept) super.clone();
        } catch (CloneNotSupportedException e) {
            return null;
        }
        return dept;
    }
}

 Fence 自定义类

package org.example.Cloneable;

import lombok.Data;

/**
 * 地理围栏类
 */
@Data
public class Fence {
    private Integer posX;
    private Integer posY;
    private Integer poxZ;
    private String FenceName;

    public Fence(Integer posX, Integer posY, Integer poxZ, String fenceName) {
        this.posX = posX;
        this.posY = posY;
        this.poxZ = poxZ;
        this.FenceName = fenceName;
    }
}

测试类

package org.example.Cloneable;

import org.junit.Test;
import java.util.Date;

public class CloneTest {
    @Test
    public void cloneDept(){
        Dept dept = new Dept("1部门", 1, 1,
                new Date(), new Fence(1, 1, 1, "name"));
        Dept copy = (Dept) dept.clone();
        System.out.println("dept: "+dept.toString());
        System.out.println("copy: "+copy.toString());

        copy.setDeptName("2222");
        copy.setTotalNum(2);
        copy.getFence().setFenceName("name2");
        System.out.println("====================");
        System.out.println("dept: "+dept.toString());
        System.out.println("copy: "+copy.toString());
    }
}

运行结果:

 从运行结果中可看出:基本数据类型 AND 不可变对象属性 String、Integer  是不会发生数据更改的,但对于自定义对象就会被copy的对象影响值,也就是意义上的没产生独立的拷贝对象,这就是所谓的浅拷贝。

深拷贝

有了上文对浅拷贝的介绍,相信大家已经对其缺陷有了一定的认识,其对对象的拷贝程度非常“浅”,那么有没有办法完全完全的拷贝一个对象,使得其所有属性均和原对象完全不相干呢?答案就是深拷贝。其通过“层层clone”的方式实现对其需要对象中的所有对象属性进行克隆

以上文为例,我们首先对Fence类实现Cloneable接口重载clone方法,由于该类中除了不可变对象属性外无其他的对象属性,故只需调用Object类中的clone方法即可,无需“层层clone”:

package org.example.Cloneable;

import lombok.Data;

/**
 * 地理围栏类
 */
@Data
public class Fence implements Cloneable{
    private Integer posX;
    private Integer posY;
    private Integer poxZ;
    private String FenceName;

    public Fence(Integer posX, Integer posY, Integer poxZ, String fenceName) {
        this.posX = posX;
        this.posY = posY;
        this.poxZ = poxZ;
        this.FenceName = fenceName;
    }

    @Override
    public Object clone() {
        Fence fence = null;
        try {
            fence = (Fence) super.clone();
        } catch (CloneNotSupportedException e) {
            return  null;
        }
        return fence;
    }
}

 对于Dept类而言,其内部除了不可变对象属性外,有createTime和fence对象属性,所以需要进行“层层clone”,分别对这两个对象进行clone,重载后clone方法如下所示:

package org.example.Cloneable;

import lombok.Data;
import java.util.Date;

/**
 * 部门类
 */
@Data
public class Dept implements Cloneable{
    private String deptName;    // 不可变对象属性
    private Integer totalNum;   // 不可变对象属性
    private int deptIdx;        // 非对象属性(基本类型属性)
    private Date createTime;    // 对象属性
    private Fence fence;       // 对象属性

    public Dept(String deptName, Integer totalNum, int deptIdx, Date createTime, Fence fence) {
        this.deptName = deptName;
        this.totalNum = totalNum;
        this.deptIdx = deptIdx;
        this.createTime = createTime;
        this.fence = fence;
    }

        @Override
        public Object clone(){
        Dept dept = null;
        try{
            dept = (Dept) super.clone();
            if( dept.getFence() != null  ) {
                Fence fence = (Fence) dept.getFence().clone();
                dept.setFence(fence);
            }
        } catch (CloneNotSupportedException e) {
            return null;
        }
        return dept;
    }
}

 运行结果:可以看出copy对象对原对象结果无影响

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值