第七节 深拷贝浅拷贝

亮子 2021-09-10 18:32:26 10905 0 0 0

深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。

假设B复制了A,修改A的时候,看B是否发生变化:

如果B跟着也变了,说明是浅拷贝,拿人手短!(修改堆内存中的同一个值)

如果B没有改变,说明是深拷贝,自食其力!(修改堆内存中的不同的值)

浅复制:仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。

深复制:在计算机中开辟一块新的内存地址用于存放复制的对象。

1)、定义技能类

@Data
public class HeroSkill {
    String skillName;
}

2)、定义英雄类

@Data
public class Hero {
    private String heroName;
    private String heroAge;

    private HeroSkill heroSkill;
}

4)、传统拷贝

public class HeroApplication {
    public static void main(String[] args) {
        //-- 新建对象
        HeroSkill skill = new HeroSkill("打虎");
        Hero hero = new Hero("武松", 19, skill);
        System.out.println(hero);

        System.out.println("========= 开始复制 ===========");

        //-- 拷贝对象
        Hero hero1 = new Hero();
        hero1.setHeroName(hero.getHeroName());
        hero1.setHeroAge(hero.getHeroAge());
        hero1.setHeroSkill(hero.getHeroSkill());
        System.out.println(hero);
        System.out.println(hero1);

        System.out.println("========= 开始修改 ===========");

        //-- 修改对象
        hero1.setHeroName("鲁智深");
        hero1.getHeroSkill().setSkillName("拔树");
        System.out.println(hero);
        System.out.println(hero1);
    }
}

4)、实现浅拷贝

浅拷贝可以通过Cloneable接口来实现。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Hero implements Cloneable {
    private String heroName;
    private Integer heroAge;

    private HeroSkill heroSkill;

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

测试代码如下:

public class HeroCloneApplication {

    public static void main(String[] args) throws CloneNotSupportedException {
        //-- 新建对象
        HeroSkill skill = new HeroSkill("打虎");
        Hero hero = new Hero("武松", 19, skill);
        System.out.println(hero);

        System.out.println("========= 开始复制 ===========");

        Hero hero1 = (Hero)hero.clone();
        System.out.println(hero);
        System.out.println(hero1);

        System.out.println("========= 开始修改 ===========");

        //-- 修改对象
        hero1.setHeroName("鲁智深");
        hero1.getHeroSkill().setSkillName("拔树");
        System.out.println(hero);
        System.out.println(hero1);
    }
}

5)、实现深拷贝

@Data
@NoArgsConstructor
@AllArgsConstructor
public class HeroSkill implements Cloneable{
    String skillName;

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

class Heros implements Cloneable {
    private String heroName;
    private String heroAge;

    private HeroSkills heroSkill;

    public Heros(String heroName, String heroAge, HeroSkills heroSkill) {
        this.heroName = heroName;
        this.heroAge = heroAge;
        this.heroSkill = heroSkill;
    }

    public Heros() {
    }

    //... get and set

    @Override
    public String toString() {
        return "name="+heroName+",age="+heroAge+",skill="+heroSkill.getSkillName();
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Heros heros = (Heros)super.clone();
        heros.setHeroSkill((HeroSkills)heroSkill.clone());

        return heros;
    }
}
public class HeroDeepCloneApplication {
    public static void main(String[] args) throws CloneNotSupportedException {
        //-- 新建对象
        HeroSkill skill = new HeroSkill("打虎");
        Hero hero = new Hero("武松", 19, skill);
        System.out.println(hero);

        System.out.println("========= 开始复制 ===========");

        Hero hero1 = (Hero)hero.clone();
        System.out.println(hero);
        System.out.println(hero1);

        System.out.println("========= 开始修改 ===========");

        //-- 修改对象
        hero1.setHeroName("鲁智深");
        hero1.getHeroSkill().setSkillName("拔树");
        System.out.println(hero);
        System.out.println(hero1);
    }
}