java clone

简介

实现Cloneable接口的类才可以被克隆,如果不实现该接口,调用Object clone方法会报CloneNotSupportedException:

InvokingObject's clone method on an instance that does not implement theCloneableinterface results in the exceptionCloneNotSupportedExceptionbeing thrown.

分类

  1. 浅克隆 指拷贝对象时仅拷贝对象本身中的基本变量,而不拷贝对象包含的引用指向的对象
  2. 深克隆 不仅拷贝对象本身中的基本变量,而且还拷贝对象中包含的引用指向的所有对象

说明

package com.lios.clone;

/**
 * @author LiosWong
 * @description
 * @date 2018/6/25 上午4:11
 */
public class Person implements Cloneable {
    private String name;

    private Worker worker;

    public Person(String name, Worker worker) {
        this.name = name;
        this.worker = worker;
    }

    public String getName() {
        return name;
    }

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

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

    public static void main(String[] args) {
        Person p = new Person("lios", new Worker("worker", 25));
        Person p1 = p;
        System.out.println("p:toString:" + p + ",hashCode:" + p.hashCode() + ",Worker:" + p.getWorker().hashCode() + ",name=" + p.getName().hashCode());
        System.out.println("p1:toString:" + p1 + ",hashCode:" + p1.hashCode() + ",Worker:" + p1.getWorker().hashCode() + ",name=" + p1.getName().hashCode());
        System.out.println(p1);


        System.out.println("=====================");

        try {
            Person p2 = (Person) p.clone();
            System.out.println("p:Worker:name:"+p.getWorker().getName());
            System.out.println("p1:Worker:name:"+p1.getWorker().getName());
            System.out.println("p2:Worker:name:"+p2.getWorker().getName());


            System.out.println("p2:toString:" + p2 + ",hashCode:" + p2.hashCode() + ",Worker:" + p2.getWorker().hashCode() + ",name=" + p2.getName().hashCode());
            p.getWorker().setName("workp");
            p.setName("cc");
            System.out.println("p2:toString:" + p2 + ",hashCode:" + p2.hashCode() + ",Worker:" + p2.getWorker().hashCode() + ",name=" + p2.getName().hashCode());
            System.out.println("p:Worker:name:"+p.getWorker().getName());
            System.out.println("p1:Worker:name:"+p1.getWorker().getName());
            System.out.println("p2:Worker:name:"+p2.getWorker().getName());
            System.out.println("p:"+p.getName());
            System.out.println("p1:"+p1.getName());
            System.out.println("p2:"+p2.getName());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }

    public Worker getWorker() {
        return worker;
    }

    public Person setWorker(Worker worker) {
        this.worker = worker;
        return this;
    }

    public static class Worker implements Cloneable {
        private String name;
        private Integer age;

        public Worker(String name, Integer age) {
            this.name = name;
            this.age = age;
        }

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

        public String getName() {
            return name;
        }

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

        public Integer getAge() {
            return age;
        }

        public Worker setAge(Integer age) {
            this.age = age;
            return this;
        }
    }
}

执行结果为:

p:toString:com.lios.clone.Person@2401f4c3,hashCode:604107971,Worker:123961122,name=3321889
p1:toString:com.lios.clone.Person@2401f4c3,hashCode:604107971,Worker:123961122,name=3321889
com.lios.clone.Person@2401f4c3
=====================
p:Worker:name:worker
p1:Worker:name:worker
p2:Worker:name:worker
p2:toString:com.lios.clone.Person@4926097b,hashCode:1227229563,Worker:123961122,name=3321889
p2:toString:com.lios.clone.Person@4926097b,hashCode:1227229563,Worker:123961122,name=3321889
p:Worker:name:workp
p1:Worker:name:workp
p2:Worker:name:workp
p:cc
p1:cc
p2:lios

发现p,p1所有的值都是一致的,当对象p中重置name属性的值、Worker属性中name的值后,p、p1、p2中属性Worker中name属性值都改变了且值相同,但是p2中的name属性值没有变化,下面用图描述:

p1与p指向堆中的同一块内存区域,p2虽然与p、p1不是指向同一块内存区域,但是它们中的Worker属性都引用同一块内存区域,其实这就是浅克隆,修改上面clone方法:

@Override
    protected Object clone() throws CloneNotSupportedException {
         Person p = (Person) super.clone();
         p.worker = (Worker) p.getWorker().clone();
         return p;
    }

再执行,结果如下:

p:toString:com.lios.clone.Person@2401f4c3,hashCode:604107971,Worker:123961122,name=3321889
p1:toString:com.lios.clone.Person@2401f4c3,hashCode:604107971,Worker:123961122,name=3321889
com.lios.clone.Person@2401f4c3
=====================
p:Worker:name:worker
p1:Worker:name:worker
p2:Worker:name:worker
p2:toString:com.lios.clone.Person@4926097b,hashCode:1227229563,Worker:1982791261,name=3321889
p2:toString:com.lios.clone.Person@4926097b,hashCode:1227229563,Worker:1982791261,name=3321889
p:Worker:name:workp
p1:Worker:name:workp
p2:Worker:name:worker
p:cc
p1:cc
p2:lios

发现此时p2中属性Worker中的name属性值没有改变,仅仅p、p1中属性Worker中的name属性值改变了,图示:

上面就是深克隆

总结

  1. 对象被clone必须实现Cloneable接口
  2. 深克隆需拷贝对象中包含的引用指向的所有对象

本文分享自微信公众号 - 后端沉思录(LiosWangs),作者:LiosWong

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-07-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • SpringMVC启动加载、请求分析

    DispatcherServlet其实是一个Servlet,用于初始化各个功能的实现类,比如异常处理、视图处理、请求映射等;且继承了FrameworkServl...

    LiosWong
  • springboot、redis整合

    LiosWong
  • 并行执行任务思考

    这篇文章由之前的并行执行任务发展而来,如何生成task,在之前的文章中,生成task方式如下:

    LiosWong
  • SSH构造struts2项目

    ydymz
  • (15)Struts2_OGNL读取Object栈

    qubianzhong
  • 58面试官居然问我Synchronized底层实现,锁升级的具体过程?

    这是我去年7,8月份面58被问的一个面试题,说实话被问到这个问题还是很意外的,感觉这个东西没啥用啊,直到后面被问了一波new Object,Integer对象等...

    Java识堂
  • Django的新增接口集管理数据库操作(十一)

    从上文的ajax请求可以看出:我们点击添加之后会调用POST,来将数据以json的格式传输给/callections/

    zx钟
  • 008.多线程-synchronized锁

    为了解决线程安全问题, 我们的做法是:不要让多个线程同时对一个全局变量作写的操作。

    qubianzhong
  • Django操作接口集编辑(十二)

    昨天完成了接口集的新增,今天继续完成它的编辑和删除功能。 首先是先写前端的Javascript代码 我们点击编辑之后应该要能跳出一个对话框,然后提示我们修改因为...

    zx钟
  • 文件操作练习.

    用户2398817

扫码关注云+社区

领取腾讯云代金券