zoukankan      html  css  js  c++  java
  • 浅谈Objeact.clone克隆(纯个人理解,如有错误请指正)

    现在先来看一下jdk给出的Object.clone源码和注释

        /**
         * Creates and returns a copy of this object.  The precise meaning
         * of "copy" may depend on the class of the object. The general
         * intent is that, for any object {@code x}, the expression:
         * <blockquote>
         * <pre>
         * x.clone() != x</pre></blockquote>
         * will be true, and that the expression:
         * <blockquote>
         * <pre>
         * x.clone().getClass() == x.getClass()</pre></blockquote>
         * will be {@code true}, but these are not absolute requirements.
         * While it is typically the case that:
         * <blockquote>
         * <pre>
         * x.clone().equals(x)</pre></blockquote>
         * will be {@code true}, this is not an absolute requirement.
         * <p>
         * By convention, the returned object should be obtained by calling
         * {@code super.clone}.  If a class and all of its superclasses (except
         * {@code Object}) obey this convention, it will be the case that
         * {@code x.clone().getClass() == x.getClass()}.
         * <p>
         * By convention, the object returned by this method should be independent
         * of this object (which is being cloned).  To achieve this independence,
         * it may be necessary to modify one or more fields of the object returned
         * by {@code super.clone} before returning it.  Typically, this means
         * copying any mutable objects that comprise the internal "deep structure"
         * of the object being cloned and replacing the references to these
         * objects with references to the copies.  If a class contains only
         * primitive fields or references to immutable objects, then it is usually
         * the case that no fields in the object returned by {@code super.clone}
         * need to be modified.
         * <p>
         * The method {@code clone} for class {@code Object} performs a
         * specific cloning operation. First, if the class of this object does
         * not implement the interface {@code Cloneable}, then a
         * {@code CloneNotSupportedException} is thrown. Note that all arrays
         * are considered to implement the interface {@code Cloneable} and that
         * the return type of the {@code clone} method of an array type {@code T[]}
         * is {@code T[]} where T is any reference or primitive type.
         * Otherwise, this method creates a new instance of the class of this
         * object and initializes all its fields with exactly the contents of
         * the corresponding fields of this object, as if by assignment; the
         * contents of the fields are not themselves cloned. Thus, this method
         * performs a "shallow copy" of this object, not a "deep copy" operation.
         * <p>
         * The class {@code Object} does not itself implement the interface
         * {@code Cloneable}, so calling the {@code clone} method on an object
         * whose class is {@code Object} will result in throwing an
         * exception at run time.
         *
         * @return     a clone of this instance.
         * @throws  CloneNotSupportedException  if the object's class does not
         *               support the {@code Cloneable} interface. Subclasses
         *               that override the {@code clone} method can also
         *               throw this exception to indicate that an instance cannot
         *               be cloned.
         * @see java.lang.Cloneable
         */
        protected native Object clone() throws CloneNotSupportedException;

    克隆对象需要继承Cloneable接口并重写Object.clone()方法,看一下bean的代码

    public class TestBean implements Cloneable{
        private Long id;
        private String code;
        private String msg;
        private TestCloneBean testCloneBean = new TestCloneBean();
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public TestCloneBean getTestCloneBean() {
            return testCloneBean;
        }
    
        public void setTestCloneBean(TestCloneBean testCloneBean) {
            this.testCloneBean = testCloneBean;
        }
    
        @Override
        protected TestBean clone() throws CloneNotSupportedException {
            return (TestBean)super.clone();
        }
    }

    克隆一个全新的对象,接下来看一下原本对象和新的克隆对象有什么区别

        public static void main(String[] args) {
            try {
                TestBean bean = new TestBean();
                TestBean copyBean = bean.clone();
                System.out.println("==判断:" + (bean == copyBean));
                System.out.println("class判断:" + (bean.getClass() == copyBean.getClass()));
                System.out.println("hasCode判断:" + (bean.hashCode() == copyBean.hashCode()));
                System.out.println("equals判断:" + (bean.equals(copyBean)));
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
        }

    看一下结果

    除了.getClass()相等,其余皆是不一样的,是一个全新的对象。

    -----------------------------------------------------------分割线-----------------------------------------------------------

    那克隆对象里面包含对象呢?我们来看一下

    public class Test {
    
        public static void main(String[] args) {
            try {
                TestBean bean = new TestBean();
                TestCloneBean testCloneBean = new TestCloneBean(1L,"1","测试");
                bean.setTestCloneBean(testCloneBean);
                TestBean copyBean = (TestBean) bean.clone();
                System.out.println("==判断:" + (bean.getTestCloneBean() == copyBean.getTestCloneBean()));
                System.out.println("class判断:" + (bean.getTestCloneBean().getClass() == copyBean.getTestCloneBean().getClass()));
                System.out.println("hasCode判断:" + (bean.getTestCloneBean().hashCode() == copyBean.getTestCloneBean().hashCode()));
                System.out.println("equals判断:" + (bean.getTestCloneBean().equals(copyBean.getTestCloneBean())));
                System.out.println("bean:{"+bean.getTestCloneBean().toString()+"}");
                System.out.println("bean:{"+copyBean.getTestCloneBean().toString()+"}");
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
        }
    }

    #1 属性testCloneBean未重写clone方法,结果是

    #2 当对象属性也重写了clone方法后

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

    结果是

    很诧异,还是原来的地址,说明对象属性是没有被克隆的,那是不是对象没有序列化呢?等我加上序列化试一下

    额~事实证明,序列化还是一样的,被克隆的对象属性是一样的!

    我不作恶

    但有权拒绝为善

    我不赞同

    但是我捍卫你不为善的权力

  • 相关阅读:
    vim 高级功能
    Vim高手,从来不用鼠标2——替换、撤销、缩进、查找
    Vim高手,从来不用鼠标
    zookeeper的leader选举机制个人总结
    【JVM】GC之垃圾收集算法
    【软件工程】常见的几种软件过程模型的比较
    【设计模式】适配器模式
    【计算机网络】网络的硬件构成要素
    【计算机网络】ISO/OSI 网络体系结构
    【Spring Cloud】Spring Cloud Config 实现分布式配置中心
  • 原文地址:https://www.cnblogs.com/HackerBlog/p/9416327.html
Copyright © 2011-2022 走看看