理解浅克隆和深克隆

浅克隆

如下图所示,浅克隆会复制基本类型的数据,原有对象和克隆对象会持有一个对引用类型的引用。

代码表现:

        


public class Email {

    /** 邮件内容 */
    private String content;

    public Email(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}
public class User implements Cloneable {

    private String name;

    private Email email;

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

    // set get construct方法省略
}

测试类


public class Demo {

    public static void main(String[] args) throws CloneNotSupportedException {
        Email email = new Email("本周六加班: 上午10点到,下午6点下班");
        User tom = new User("TOM", email);

        User Lily = (User) tom.clone();
        Lily.setName("Lily");

        User Jack = (User) tom.clone();
        Jack.setName("Jack");

        System.out.println("###############################################");
        System.out.println("##               邮件通知                     ");
        System.out.println("##                                          ");
        System.out.println("##  " + tom.getName() + ": " + tom.getEmail().getContent());
        System.out.println("##  " + Lily.getName() + ": " + Lily.getEmail().getContent());
        System.out.println("##  " + Jack.getName() + ": " + Jack.getEmail().getContent());

        System.out.println();
        System.out.println("###############################################");
        System.out.println("##               个人邮件通知                     ");
        System.out.println("##                                          ");
        Jack.getEmail().setContent("加个毛线班");
        System.out.println("##  " + tom.getName() + ": " + tom.getEmail().getContent());
        System.out.println("##  " + Lily.getName() + ": " + Lily.getEmail().getContent());
        System.out.println("##  " + Jack.getName() + ": " + Jack.getEmail().getContent());
    }
}

结果:

可以看到,当我们修改其中某一个用户的引用类型Email 的时候,所有的人的Email 都变了。

深克隆

对Email 对象实现 Cloneable 方法并重写 clone方法

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

然后修改User中的clone方法

@Override
protected Object clone() throws CloneNotSupportedException {
    User user = (User) super.clone();
    user.setEmail((Email) email.clone());
    return user;
}

结果:

###############################################
##               邮件通知                     
##                                          
##  TOM: 本周六加班: 上午10点到,下午6点下班
##  Lily: 本周六加班: 上午10点到,下午6点下班
##  Jack: 本周六加班: 上午10点到,下午6点下班

###############################################
##               个人邮件通知                     
##                                          
##  TOM: 本周六加班: 上午10点到,下午6点下班
##  Lily: 本周六加班: 上午10点到,下午6点下班
##  Jack: 加个毛线班

总结:需要对深克隆对象中的引用类型实现Cloneable接口,并重写clone方法,并在被引用对象调用引用类型的clone方法,

User user = (User) super.clone();

user.setEmail((Email) email.clone());


方案二:引用类型实现序列化接口

implements Serializable

增加一个自定义deepclone0 方法

public User deepClone() throws IOException, ClassNotFoundException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream objOutStream = new ObjectOutputStream(baos);
    objOutStream.writeObject(this);
    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    ObjectInputStream objInputStream = new ObjectInputStream(bais);
    return (User) objInputStream.readObject();
}

原理:ObjectOutputStream 、ObjectInputStream 先将对象写入到磁盘,再通过流从磁盘中读到内存,这样每次读来的Object都是一个新的对象。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值