栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > .Net

Cloneable接口以及深拷贝和浅拷贝

.Net 更新时间:发布时间: 百科书网 趣学号

目录

1.Cloneable接口

1.1Cloneable接口中什么方法都没有,那为什么要继承该接口?

1.2.Cloneable接口什么方法都没有,那我该重写谁的clone()方法来实现对象拷贝?

1.3.实现对象拷贝的方法步骤

1.3.1让Person类实现Cloneadble接口

1.3.2重写Object的clone()方法

1.3.3注意抛异常和和向下转型

1.4.代码实现

2.深拷贝

3.浅拷贝

如何发生浅拷贝?

 将浅拷贝变成深拷贝的思路


1.Cloneable接口

1.1Cloneable接口中什么方法都没有,那为什么要继承该接口?

解答:在Cloneable接口的源码中,里面什么方法都没有,但是implements该接口的类则证明该类是可以被克隆的。


Cloneable接口源码

1.2.Cloneable接口什么方法都没有,那我该重写谁的clone()方法来实现对象拷贝?

解答:所有类都默认继承Object类,所以需要重写Object类中的clone()方法就能实现对象的拷贝了。

1.3.实现对象拷贝的方法步骤

我以自定义Person类举例

1.3.1让Person类实现Cloneadble接口

1.3.2重写Object的clone()方法

1.3.3注意抛异常和和向下转型

1.4.代码实现
class Person implements Cloneable{
    public int age;
    public int id;

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

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", id=" + id +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class CloneableDemo {
    public static void main(String[] args) throws CloneNotSupportedException{
        Person person1 = new Person(10,0001);
        //1.由于重写的clone方法会抛出编译时异常,要么try-catch,要么继续抛
        //2.clone()方法返回值为Object类型,因此需要向下转型
        Person person2 = (Person)person1.clone();
        System.out.println(person1);
        System.out.println(person2);
    }
}

结果:

 图解代码:

2.深拷贝

简单理解:我改变person1对象中的属性值,不会影响到person2对象中的属性值,那么就叫做深拷贝。

从上图中可知,如果我修改person1对象的age属性为200,id属性也为200,应该是不会影响person2对象的属性值的。

直接看代码:

结果:可以发现,改变了person1对象中的成员变量的值,并不会影响person2中成员变量的值。

3.浅拷贝

简单理解:我改变person1对象中的属性值,会影响到person2对象中的属性值,那么就叫做深拷贝。

看到这块基本上也就理解了Cloneable接口、深浅拷贝了。

接下来会说一说,如何发生浅拷贝,以及如何将浅拷贝转化为深拷贝。

---------------------------------------------------------------------------------------------------------------------------------

如何发生浅拷贝?

如下图所示,如果给我的Person类当中再添加一个引用类型的成员变量 ,那此时在调用clone()方法时,拷贝的副本(person2所指的对象)会将原对象当中的所有值全部拷贝,此时副本中的引用类型变量也存储的是0x999的地址,那么也就会让副本中的引用类型变量和原对象的引用类型变量指向同一片空间。如果指向了同一片空间,修改person1对象中引用类型的变量值就会让person2的变量值也会发生改变,那是不是就发生了浅拷贝!!!

代码演示:再自定义一个Money类,在Person类中定义一个Money类型的变量。

给person1.money.salary = 12,person2.money.salary = 200

 结果:结果最终都是200,这次是浅拷贝了,但我们希望他们两个对象互不影响(也就是深拷贝)

 将浅拷贝变成深拷贝的思路

方法一:

1.我们可以先将引用类型(Money)所指向的对象拷贝一份

2.接着我们在拷贝Person类的对象

3.让Person类对象的引用变量指向最初拷贝的那个(Money)对象

画个图解释一下

 核心代码的实现:

 结果:

 源代码:
 

class Money implements Cloneable{
    public int salary;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable{
    public int age;
    public int id;
    public Money money = new Money();


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

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", id=" + id +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class CloneableDemo {
    public static void main(String[] args) throws CloneNotSupportedException{
        Person person1 = new Person(10,0001);
        person1.money.salary = 12;
        //1.先拷贝money对象
        Money temp = (Money)person1.money.clone();
        //2.在拷贝person2对象
        Person person2 = (Person)person1.clone();
        //3.person2.money指向temp
        person2.money = temp;
        person2.money.salary = 200;
        System.out.println(person1.money.salary);
        System.out.println(person2.money.salary);
    }
}

方法二:

方法一是在main方法中进行修改的,我们希望调用完clone()方法就能做到深拷贝,因此需要修改Person类中的clone方法

图解:

核心代码块:

结果:两者已经互不影响了

源代码:

class Money implements Cloneable{
    public int salary;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable{
    public int age;
    public int id;
    public Money money = new Money();


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

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", id=" + id +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //先克隆一个Person对象副本
        Person personTemp = (Person)super.clone();
        //2.在克隆money对象的副本,并将副本的money指向克隆出来的money对象
        personTemp.money = (Money)this.money.clone();
        //3.返回该Person类对象的引用
        return personTemp;
    }
}
public class CloneableDemo {
    public static void main(String[] args) throws CloneNotSupportedException{
        Person person1 = new Person(10,0001);
        person1.money.salary = 12;
        Person person2 = (Person)person1.clone();
        person2.money.salary = 200;
        System.out.println(person1.money.salary);
        System.out.println(person2.money.salary);
    }
}

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/985001.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号