个人理解Java的浅克隆与深克隆

本文介绍了浅克隆和深克隆的区别,浅克隆只克隆基本数据和String,深克隆则复制所有引用对象。讲解了如何通过实现Cloneable接口和序列化技术进行克隆,并分析了各种方法的优缺点。

浅克隆

浅克隆只会克隆基本数据属性,而不会克隆引用其他对象的属性,String类型除外。(String对象是不可修改的对象,每次修改其实都是新建一个新的对象,而不是在原有的对象上修改,所以当修改String属性时其实是新开辟一个空间存储String对象,并把引用指向该内存,而克隆出来的对象的String属性还是指向原有的内存地址,所以String对象在浅克隆中也表现得与基本属性一样。)

如果你需要拷贝的对象只包含基本数据类型和String直接用浅克隆也没什么影响。

 

步骤

  1. 对象的类需要实现Cloneable接口
  2. 重写Object类中的clone()方法
  3. 根据重写的clone()方法得到想要的克隆结果

 示例:

public class Person  implements  Cloneable{
    private  int age ;
    private  String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public Person() {
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    @Override
    protected Person clone() throws CloneNotSupportedException {
        return (Person) super.clone();
    }
}
 public static void main(String[] args) throws ClassNotFoundException, CloneNotSupportedException {
        Person person = new Person(11,"aa");
        Person newPerson  = person.clone();
        person.setAge(21);
        person.setName("bb");
        System.out.println(person.toString());
        System.out.println(newPerson.toString());
    }

 深克隆

深克隆会把原型对象和原型对象所引用的对象,都复制一份给克隆对象。原对象和克隆对象完全不搭噶(不搭噶:完全独立,没有关系。)

 实现方式

  1. 实现 Cloneable 接口并重写 Object 类中的 clone()
  2. 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆
  3. 通过第三方工具,如Gson、Jackson

优缺点 

深拷贝方法

优点

缺点

重写clone()方法

1. 底层实现较简单

2. 不需要引入第三方包

3. 系统开销小

1. 可用性较差,每次新增成员变量可能需要修改clone()方法

2. 拷贝类(包括其成员变量)需要实现Cloneable接口

Apache.Commons.Lang序列化

1. 可用性强,新增成员变量不需要修改拷贝方法

1. 底层实现较复杂

2. 需要引入Apache Commons Lang第三方JAR包

3. 拷贝类(包括其成员变量)需要实现Serializable接口

4. 序列化与反序列化存在一定的系统开销

Gson序列化

1. 可用性强,新增成员变量不需要修改拷贝方法

2. 对拷贝类没有要求,不需要实现额外接口和方法

1. 底层实现复杂

2. 需要引入Gson第三方JAR包

3. 序列化与反序列化存在一定的系统开销

Jackson序列化

1. 可用性强,新增成员变量不需要修改拷贝方法

1. 底层实现复杂

2. 需要引入Jackson第三方JAR包

3. 拷贝类(包括其成员变量)需要实现默认的无参构造函数

4. 序列化与反序列化存在一定的系统开销

 



public class Attribute implements  Cloneable{
    //战力值
    private  int  combatPowerValue;
    //防御值
    private  int  defenseValue;

    public Attribute(int combatPowerValue, int defenseValue) {
        this.combatPowerValue = combatPowerValue;
        this.defenseValue = defenseValue;
    }

    public int getCombatPowerValue() {
        return combatPowerValue;
    }

    public void setCombatPowerValue(int combatPowerValue) {
        this.combatPowerValue = combatPowerValue;
    }

    public int getDefenseValue() {
        return defenseValue;
    }

    public void setDefenseValue(int defenseValue) {
        this.defenseValue = defenseValue;
    }

    @Override
    public String toString() {
        return "Attribute{" +
                "combatPowerValue=" + combatPowerValue +
                ", defenseValue=" + defenseValue +
                '}';
    }

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


public class Person  implements  Cloneable{
    private  int age ;
    private  String name;
    private  Attribute attribute;

    public Person(int age, String name, Attribute attribute) {
        this.age = age;
        this.name = name;
        this.attribute = attribute;
    }

    public Person() {
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Attribute getAttribute() {
        return attribute;
    }

    public void setAttribute(Attribute attribute) {
        this.attribute = attribute;
    }

    @Override
    protected Person clone() throws CloneNotSupportedException {
        Person clone = (Person) super.clone();
        //如果有多个引用对象,需要每个对象都需要重新设置,不灵活。
        clone.setAttribute(this.attribute.clone());
        return clone;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", attribute=" + attribute +
                '}';
    }
}
   public static void main(String[] args) throws ClassNotFoundException, CloneNotSupportedException {
        Attribute attribute = new Attribute(1000, 200);
        Person person = new Person(11,"aa",attribute);
        Person newPerson  = person.clone();
        person.setAge(21);
        person.setName("bb");
        person.getAttribute().setCombatPowerValue(500);
        System.out.println(person.toString());
        System.out.println(newPerson.toString());
    }

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值