Java-克隆

  • 假克隆
    • 1测试代码
    • 2输出结果
    • 3结果分析
  • 浅克隆
    • 1测试代码
    • 2输出结果
    • 3结果分析
  • 深克隆
    • 测试代码
    • 输出结果
    • 结果分析
  • 总结

1.假克隆

1.1测试代码

 /** * 假克隆 * <p> * 只复制了对象,没有复制对象的引用 */
    private static void testFakeClone() {
        //源对象
        Bean bean = new Bean("张三", new Boss("老大"));

        //这是克隆对象
        Bean clone = bean;
        clone.setName("小明");
        clone.getBoss().setName("头");

        System.out.println("这是原始数据:");
        System.out.println(JSON.toJSONString(bean));
        System.out.println("这是假克隆:");
        System.out.println(JSON.toJSONString(clone));
    }

1.2.输出结果:

//这是原始数据:
{
“boss”: {
“name”: “头”
},
“name”: “小明”
}
//这是假克隆:
{
“boss”: {
“name”: “头”
},
“name”: “小明”
}

1.3.结果分析:

这里,我们修改了克隆对象的属性之后,源对象的属性也同样变了,关系如图所示(图是盗来的,不要纠结于名称):
Java-克隆_第1张图片

2.浅克隆

2.1.测试代码:

/** * 浅克隆 * <p> * 既复制了对象,也复制了对象的引用 * 但是如果引用还存在引用,而更深层的引用如果没有实现cloneable接口,就还是会指向源对象 */
    private static void testShallowClone() {
        //源对象
        Bean bean = new Bean("张三", new Boss("老大"));

        //这是克隆对象
        Bean clone = bean.clone();
        clone.setName("小明");
        clone.getBoss().setName("头");

        System.out.println("这是原始数据:");
        System.out.println(JSON.toJSONString(bean));
        System.out.println("这是浅克隆:");
        System.out.println(JSON.toJSONString(clone));
    }

需要Bean实现Cloneable接口:

/** * 被克隆对象 * <p> */
    public static class Bean implements Cloneable {
        private String name;
        private Boss boss;

        public Bean() {
        }

        public Bean(String name, Boss boss) {
            this.name = name;
            this.boss = boss;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Boss getBoss() {
            return boss;
        }

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

        @Override
        protected Bean clone() {
            Bean clone = null;
            try {
                clone = (Bean) super.clone();

            } catch (CloneNotSupportedException e) {
                throw new RuntimeException(e);
            }
            return clone;
        }
    }

2.2.输出结果:

//这是原始数据:
{
“boss”: {
“name”: “头”
},
“name”: “张三”
}
//这是浅克隆:
{
“boss”: {
“name”: “头”
},
“name”: “小明”
}

2.3.结果分析:

这里,我们修改了克隆对象的属性之后,源对象的name属性没有变,但是更深的引用boss却变了,说明此时源对象和克隆对象所引用的boss对象,其实还是同一个,关系如图所示(图是盗来的,不要纠结于名称):
Java-克隆_第2张图片

深克隆

测试代码:

/** * 深克隆 * <p> * 将对象序列化,再反序列化生成一个新对象即可 * Serializable、Parcelable、JSON等均可 */
    private static void testDeepClone() {
        //源对象
        Bean bean = new Bean("张三", new Boss("老大"));

        //这是克隆对象
        String json = JSON.toJSONString(bean);
        Bean clone = JSON.parseObject(json, Bean.class);
        clone.setName("小明");
        clone.getBoss().setName("头");

        System.out.println("这是原始数据:");
        System.out.println(JSON.toJSONString(bean));
        System.out.println("这是深克隆:");
        System.out.println(JSON.toJSONString(clone));
    }

输出结果:

//这是原始数据:
{
“boss”: {
“name”: “老大”
},
“name”: “张三”
}
//这是深克隆:
{
“boss”: {
“name”: “头”
},
“name”: “小明”
}

结果分析:

总结:

  1. clone在平时项目中虽然用的不多,但是,区分深克隆和浅克隆却可以帮助我们理解java的内存结构
  2. clone的深克隆其实就是序列化和反序列化,这里有很多种选择,Serializable、Parcelable、JSON等均可
  3. clone方法不同于new方法,不会执行构造方法

参考目录:
1. 详解Java中的clone方法 – 原型模式

你可能感兴趣的:(Java-克隆)