解析java克隆、拷贝原理 + 案例解析

发布于:2022-07-25 ⋅ 阅读:(412) ⋅ 点赞:(0)

解析java克隆、拷贝原理 + 案例解析

复习clone 原理用法

浅拷贝:概念

  1. 数据类型是基本数据类型的浅拷贝,拷贝会直接进行值传递,也就是将原对象的属性赋值一份给新对象,因为是两份不同的数据,所以对其中一个对象的成员变量进行修改,不会影响另一个对象的属性
  2. 数据类型是引用数据类型的浅拷贝,拷贝进行引用传递,即将地址复制一个给拷贝对象,所以两个对象的引用地址是一样的,如果修改其中一个对象的引用值,会影戏到另一个对象的变量值

例题:

​ 定义英雄类,英雄有角色名字、攻击力、防御力、武器(String)
​ 测试类中实例化一个英雄,拥有一把武器,名字是屠龙、攻击力加成为100

通过内存结构图进行分析,该例题,因为比较简单,就不上传代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JSNleIzy-1658759184951)(D:\桌面\浅拷贝.png)]

浅拷贝:概念

深拷贝后的对象与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象,通过例题更好理解

例题:

​ 定义英雄类,英雄有角色名字、攻击力、防御力、武器
​ 定义武器类,武器有名字、攻击力加成、耐久值
​ 测试类中实例化一个英雄,拥有一把武器,名字是屠龙、攻击力加成为100
​ 耐久值为1000
​ 然后复制这个英雄,复制出来的英雄的武器,名字是屠龙、攻击力加成为100、
​ 耐久值为467

  • 思路
  1. 先创建一个武器类(Arm),因为要进行拷贝,所以要实现 implemensts Cloneable接口
  2. 一个英雄类(Hero),属性中有武器,Arm arm,因为要进行拷贝,所以要实现implemensts Cloneable接口
  3. 在英雄类中重定义clone 方法时,要用重新进行 武器的clone,原理很简单,克隆出来了一个英雄,肯定要克隆出来一把相同的武器呀,因为武器是引用数据类型,所以这里一定要写,不要后面的耐久值修改不了
  4. 最后是测试类,通过英雄类 . 武器类 . 耐久值,进行属性的修改

内存结构图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7fOuQYwq-1658759184952)(D:\图片\实训重点知识\深拷贝原理图.png)]

// 武器类
package kaobeiPractice;

public class Arm implements Cloneable{
    private String name;
    private double addAttack;
    private double endurance;//耐久值
    public Arm() {}
    public Arm(String name, double addAttack, double endurance) {
        this.name = name;
        this.addAttack = addAttack;
        this.endurance = endurance;
    }
    public String getName() {
        return name;
    }
    @Override
    public String toString() {
        return "Arm{" +
                "name='" + name + '\'' +
                ", addAttack=" + addAttack +
                ", endurance=" + endurance +
                '}';
    }
    @Override
    public Arm clone()  {
       Arm arm =null;
        try{
            arm = (Arm)super.clone();
        }catch (CloneNotSupportedException e ) {
            e.printStackTrace();
        }
       return arm;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getAddAttack() {
        return addAttack;
    }
    public void setAddAttack(double addAttack) {
        this.addAttack = addAttack;
    }
    public double getEndurance() {
        return endurance;
    }
    public void setEndurance(double endurance) {
        this.endurance = endurance;
    }
}
// 英雄类
package kaobeiPractice;

// 使用克隆,要实现cloneable 接口
public class Hero implements Cloneable{
    private String name;
    private double attack;//攻击力
    private double defence;//防御力
    private Arm arm;//武器
    public Hero() {}
    public Hero(String name, double attack, double defence, Arm arm) {
        this.name = name;
        this.attack = attack;
        this.defence = defence;
        this.arm = arm;
    }
    @Override
    public String toString() {
        return "Hero{" +
                "name='" + name + '\'' +
                ", attack=" + attack +
                ", defence=" + defence +
                ", arm=" + arm +
                '}';
    }
    @Override
    public Hero clone() {
        Hero hero = null;
        try {
            hero = (Hero)super.clone();
//            英雄都被克隆了一份,武器理所当然的也会被克隆一份赛! 武器也需要克隆一份
            setArm(getArm().clone());  //相当于是new 了 一个 Arm 武器
        }catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return hero;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getAttack() {
        return attack;
    }
    public void setAttack(double attack) {
        this.attack = attack;
    }
    public double getDefence() {
        return defence;
    }
    public void setDefence(double defence) {
        this.defence = defence;
    }
    public Arm getArm() {
        return arm;
    }
    public void setArm(Arm arm) {
        this.arm = arm;
    }
}
//测试类
package kaobeiPractice;
public class Test {
    public static void main(String[] args) {
        Arm arm = new Arm("铁剑?",100,1000);
        Hero hero = new Hero("西门飞雪",100,50,arm);
        Hero copyHero = hero.clone();
        copyHero.setAttack(copyHero.getAttack()+100);
        copyHero.getArm().setEndurance(475);
        System.out.println(hero);
        System.out.println(copyHero);
    }
}

感悟

  1. 进行拷贝的使用要清楚拷贝的步骤,1.拷贝的类一定要实现Cloneable接口
  2. clone拷贝默认是浅拷贝,拷贝引用数据类型是的时候,要进行深拷贝,一定要考虑在重写clone 方法的时候要clone几个引用数据类型,这里比较容易出问题(我就是出问题出在这里)
  3. String 虽然是引用数据类型,但是是final 类型,是不能修改的值,同时也有字符串常量池的存在,不需要进行处理
  4. 今天的克隆学习有点困难,还要继续加油!

网站公告

今日签到

点亮在社区的每一天
去签到