详解Java浅拷贝,通俗易懂

概念

浅拷贝:创建一个对象,然后将当前对象的非静态字段复制出来,形成一个新对象。如果字段是值类型的,那么对该字段执行复制,如果该字段是引用类型的,则复制引用但不复制引用的对象内容。因此,原始对象及其副本对象的非基本数据类型的属性会引用同一个对象。

代码

@Data
public class Person implements Cloneable{
    private String name;
    private int id;
    private Person child;

    @Override
    public Person clone(){
        try {
            return (Person) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }
}
```java
public class TestClone {

    @Test
    public void testClone(){
        Person person = new Person();
        person.setId(1);
        person.setName("小明");

        Person child = new Person();
        child.setId(2);
        child.setName("小龙");

        person.setChild(child);

        Person clone = person.clone();
        System.out.println("刚克隆好时person:"+person);
        System.out.println("刚克隆好时clone:"+clone);
        System.out.println("刚克隆好时person child hashcode:"+person.getChild().hashCode());
        System.out.println("刚克隆好时clone child hashcode:"+clone.getChild().hashCode());

        System.out.println("刚克隆好时person name hashcode:"+person.getName().hashCode());
        System.out.println("刚克隆好时clone name hashcode:"+clone.getName().hashCode());
        clone.setName("小明2");
        System.out.println("克隆对象修改name之后person name hashcode:"+person.getName().hashCode());
        System.out.println("克隆对象修改name之后clone name hashcode:"+clone.getName().hashCode());
        System.out.println("克隆对象修改name之后person:"+person);
        System.out.println("克隆对象修改name之后clone:"+clone);

        clone.getChild().setName("小龙2");
        System.out.println("克隆对象的child属性修改name之后person:"+person);
        System.out.println("克隆对象的child属性修改name之后clone:"+clone);

    }

输出结果解释

前四个输出

System.out.println("刚克隆好时person:"+person);
System.out.println("刚克隆好时clone:"+clone);
System.out.println("刚克隆好时person child hashcode:"+person.getChild().hashCode());
System.out.println("刚克隆好时clone child hashcode:"+clone.getChild().hashCode());

刚克隆好时person:Person(name=小明, id=1, child=Person(name=小龙, id=2, child=null))
刚克隆好时clone:Person(name=小明, id=1, child=Person(name=小龙, id=2, child=null))
刚克隆好时person child hashcode:45726990    
刚克隆好时clone child hashcode:45726990

1.这里刚克隆好,原始数据和clone数据的的child的hashcode一样,说明person和clone的child是同一个对象。

中间的输出

  	System.out.println("刚克隆好时person name hashcode:"+person.getName().hashCode());
    System.out.println("刚克隆好时clone name hashcode:"+clone.getName().hashCode());
    clone.setName("小明2");
    System.out.println("克隆对象修改name之后person name hashcode:"+person.getName().hashCode());
    System.out.println("克隆对象修改name之后clone name hashcode:"+clone.getName().hashCode());
    System.out.println("克隆对象修改name之后person:"+person);
    System.out.println("克隆对象修改name之后clone:"+clone);
 * 刚克隆好时person name hashcode:756703
 * 刚克隆好时clone name hashcode:756703
 * 克隆对象修改name之后person name hashcode:756703
 * 克隆对象修改name之后clone name hashcode:23457843        
 * 克隆对象修改name之后person:Person(name=小明, id=1, child=Person(name=小龙, id=2, child=null))
 * 克隆对象修改name之后clone:Person(name=小明2, id=1, child=Person(name=小龙, id=2, child=null))

2.刚克隆好时person和clone对象的name属性hashcode是一样的,此时他们俩的name是同一个对象,修改clone对象的name之后,clone对象的name的hashcode变了,说明已经换了一个对象。

3.这里说明String类型的数据修改并不会影响原始数据,因为String每次修改都是重新创建了新的String对象,这里是吧新的String对象的引用给了clone对象的name,所以地址也变了,但不会影响person的。

最后的输出

    clone.getChild().setName("小龙2");
    System.out.println("克隆对象的child属性修改name之后person:"+person);
    System.out.println("克隆对象的child属性修改name之后clone:"+clone);
 * 克隆对象的child属性修改name之后person:Person(name=小明, id=1, child=Person(name=小龙2, id=2, child=null))
 * 克隆对象的child属性修改name之后clone:Person(name=小明2, id=1, child=Person(name=小龙2, id=2, child=null))

4.修改child属性的name之后,发现原始数据person和clone数据的name都变了,也就跟上面1所说的,person和clone的child是同一个对象。

疑问

以下结果是什么原因呢?

刚克隆好时person hashcode:90581327
刚克隆好时clone hashcode:90581327

克隆对象修改name之后person hashcode:90581327
克隆对象修改name之后clone hashcode:1429948587

最后person hashcode:1456022457
最后clone hashcode:-1499577579

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值