Java的克隆原理

今天的记录是java的克隆机制以及深克隆和浅克隆,话不多说,线上代码:

public static class Boss{
        private int number;

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }
    }

    public static class Boy implements Cloneable{
        private Boss boss;
        private int number;
        private List<Integer> list=new ArrayList<>();

        public Boy(){
            boss=new Boss();
        }

        public Boss getBoss() {
            return boss;
        }

        public void setBoss(Boss boss) {
            this.boss = boss;
        }

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }

        @Override
        public String toString() {
            return super.toString();
        }

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

我们这里的boy是指小弟,boss是老板,于是小弟会对应一个老板,但是老板没有实现克隆而只有小弟实现了克隆,测试一下会有什么样的结果呢?

public static void main(String[] args) throws Exception{
        Boy boy1=new Boy();
        boy1.boss.setNumber(0);
        boy1.setNumber(0);

        Boy boy2=(Boy) boy1.clone();
        boy2.boss.setNumber(1);
        boy2.setNumber(1);

        System.out.println(boy1.boss.number);
        System.out.println(boy2.boss.number);
        System.out.println(boy1.number);
        System.out.println(boy2.number);
    }

输出结果:

boy1 number 1
boy2 number 1
boy1 boss number 0
boy2 boss number 1

可以看到,boy.name是克隆了,但是boy.boss依然没有被克隆,其实这里的原因是java的克隆机制问题。直接调用java的克隆发生的都是浅克隆,即对于基本数据类型直接拷贝,而对于对象则拷贝对象的引用,因此要成功克隆boss,需要这么改:

public static class Boss implements Cloneable{
        private int number;

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }

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

    public static class Boy implements Cloneable{
        private Boss boss;
        private int number;
        private List<Integer> list=new ArrayList<>();

        public Boy(){
            boss=new Boss();
        }

        public Boss getBoss() {
            return boss;
        }

        public void setBoss(Boss boss) {
            this.boss = boss;
        }

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }

        @Override
        public String toString() {
            return super.toString();
        }

        @Override
        public Object clone() throws CloneNotSupportedException {
            Boy boy=(Boy) super.clone();
            boy.boss=(Boss) this.boss.clone();

            return boy;
        }
    }

再次运行:

boy1 number 0
boy2 number 1
boy1 boss number 0
boy2 boss number 1

事实上clone不是一种实现深克隆的好办法,真正实现深克隆的最好的办法是使用序列化与反序列化:

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) throws Exception{
        Boy boy1=new Boy();
        boy1.setNumber(0);
        boy1.boss.setNumber(0);

        Boy boy2=clone(boy1);
        boy2.setNumber(1);
        boy2.boss.setNumber(1);

        System.out.println(boy1.boss.number);
        System.out.println(boy2.boss.number);
        System.out.println(boy1.number);
        System.out.println(boy2.number);
    }

    public static class Boss implements Serializable{
        private int number;

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }
    }

    public static class Boy implements Serializable{
        private Boss boss;
        private int number;
        private List<Integer> list=new ArrayList<>();

        public Boy(){
            boss=new Boss();
        }

        public Boss getBoss() {
            return boss;
        }

        public void setBoss(Boss boss) {
            this.boss = boss;
        }

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }
    }

    public static <T> T clone(T obj) throws Exception{
        ByteArrayOutputStream bout=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bout);
        oos.writeObject(obj);

        ByteArrayInputStream bin=new ByteArrayInputStream(bout.toByteArray());
        ObjectInputStream ois=new ObjectInputStream(bin);
        return (T) ois.readObject();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值