认识深浅拷贝及clone方法

深浅拷贝

1 认识浅拷贝

什么是浅拷贝?

我们一起来看一段代码了解一下

public class Blog {
    public static void main(String[] args) {
        String s1 = new String("我是原件");//一般来说不建议使用new的方法创造String的对象,这样会导致常量池中的String浪费,并且堆中占用内存
        String s2 = s1;
        System.out.println(s2);
    }
}
/*
	我是原件
*/

其实浅拷贝就是我们平时用的最多,也是最简单的,我们也把它叫做对象拷贝,我们只需要让副本的引用指向原件的对象,这样也就实现了两个地址相同,指向同一个对象,因此两个引用没有区别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IzXJDthU-1652285831913)(C:\Users\小艺\AppData\Roaming\Typora\typora-user-images\image-20220414133839999.png)]

这样的话会有什么不方便的地方呢?

我们修改其中“一个”对象的值的时候,会导致另一个对象也出现相应的修改

public class Blog {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Dog dog1 = dog;
        System.out.println(dog1.getMood());
        dog.setMood("心情不好");
        System.out.println(dog1.getMood());
    }
}
/*
	心情好
	心情不好
*/

我们可以看到,先创建一个Dog对象,引用dog指向它,并且默认设置为心情好

然后dog1引用指向引用dog,我们之后修改dog对象的属性,dog1也会随之改变

2 认识深拷贝

只复制 引用数据类型中的 数值 而不是 复制地址,称为深拷贝

其中需要用到clone()方法,该方法来自于Object类,因此所有类中都含有此方法

public class Blog {
    public static void main(String[] args) throws CloneNotSupportedException {
        Dog dog = new Dog();
        Dog dog1 = (Dog) dog.clone();
        System.out.println(dog1.getMood());
        dog.setMood("心情不好");
        System.out.println(dog1.getMood());
    }
}
/*
	心情好
	心情好
*/

深拷贝又叫做对象拷贝,这样的操作,我们只是获得对象的各个字段的值,达到一种克隆的效果,这样我们改变其中一个对象的值不会影响另一个对象的值,这就叫做深拷贝,两个对象的值也是不同的。

深浅拷贝都是对象拷贝。

3 总结

我们在重写clone方法时,需要实现Cloneable接口

例如

public class House implements Cloneable{
    Person p;

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

下面这一段代码

public class House implements Cloneable{
    Person p;

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

public class Main {
    public static void main(String[] args) {
        House house = new House();
        house.p=new Person();
        System.out.println("house"+house+"                   "+"person:"+house.p);
        House house1 = null;
        try{
            house1 = (House) house.clone();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("house"+house1+"                   "+"person:"+house1.p);
    }
}
/*
运行结果
housecom.fq.clone.House@14ae5a5           person:com.fq.clone.Person@7f31245a
housecom.fq.clone.House@6d6f6e28          person:com.fq.clone.Person@7f31245a

*/

可以看到House对象是被重新拷贝了一份,但是其中的Person对象却还是原来的值,这说明clone方法默认是浅拷贝

我们可以这样解决这个问题

public class House implements Cloneable{
    Person p;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        House house = null;
        try {
            house = (House) super.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        house.p = (Person) this.p.clone();
        return house;
    }
}

public class Person implements Cloneable{

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

public class Main {
    public static void main(String[] args) {
        House house = new House();
        house.p=new Person();
        System.out.println("house"+house+"                   "+"person:"+house.p);
        House house1 = null;
        try{
            house1 = (House) house.clone();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("house"+house1+"                   "+"person:"+house1.p);
    }
}
/*
运行结果
housecom.fq.clone.House@14ae5a5              person:com.fq.clone.Person@7f31245a
housecom.fq.clone.House@6d6f6e28             person:com.fq.clone.Person@135fbaa4
*/

当一个对象是引用数据类型,并且他的成员属性中也有引用数据类型,这时候我们让所有的引用数据类型都实现Cloneable接口,并且重写其中的clone方法。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值