zoukankan      html  css  js  c++  java
  • Java浅克隆和深度克隆

    .java里的clone分为: 
    A:浅复制(浅克隆): 浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。 
    b:深复制(深克隆):深复制把要复制的对象所引用的对象都复制了一遍。 
    Java中对象的克隆,为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。必须要遵循下面三点 
    1.在派生类中覆盖基类的clone()方法,并声明为public【Object类中的clone()方法为protected的】。 
    2.在派生类的clone()方法中,调用super.clone()。 
    3.在派生类中实现Cloneable接口。 

    浅复制(shallow clone):

    被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。

    深复制(deep clone):

    被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

    Object中的clone方法:
    clone
    protected Object clone()
                    throws CloneNotSupportedException
    创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。这样做的目的是,对于任何对象 x,表达式: 
            x.clone() != x
    为 true,表达式: 
           x.clone().getClass() == x.getClass()
    也为 true,但这些并非必须要满足的要求。一般情况下: 
           x.clone().equals(x)
    为 true,但这并非必须要满足的要求。 
        按照惯例,返回的对象应该通过调用 super.clone 获得。如果一个类及其所有的超类(Object 除外)都遵守此约定,则 x.clone().getClass() == x.getClass()。

    按照惯例,此方法返回的对象应该独立于该对象(正被复制的对象)。要获得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段进行修改。这通常意味着要复制包含正在被复制对象的内部“深层结构”的所有可变对象,并使用对副本的引用替换对这些对象的引用。如果一个类只包含基本字段或对不变对象的引用,那么通常不需要修改 super.clone 返回的对象中的字段。

    Object 类的 clone 方法执行特定的复制操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。注意,所有的数组都被视为实现接口 Cloneable。否则,此方法会创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;这些字段的内容没有被自我复制。所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。

    Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。

    Object的clone方法的说明:

    在运行时刻,Object中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。

    继承自java.lang.Object类的clone()方法是浅复制。

    Java中实现对象的克隆:
    ①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。
    ②在派生类中覆盖基类的clone()方法,并声明为public。
    ③在派生类的clone()方法中,调用super.clone()。
    ④在派生类中实现Cloneable接口(一个标识性的接口)。
     
    import java.util.Date;
    
    public class ShallowCopy implements Cloneable{
    
        private Date begin;
        public Date getBegin(){
            return this.begin;
        }
        public void setBegin(Date d){
            this.begin=d;
        }
        public Object clone(){
            Object obj=null;
            try {
                obj=super.clone();
            } catch (CloneNotSupportedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return obj;
        }
    }
    //上面是浅克隆,下面是深度克隆的例子
    import java.util.Date;
    
    public class DeepCopy implements Cloneable{
    
        private Date begin;
        public Date getBegin(){
            return this.begin;
        }
        public void setBegin(Date d){
            this.begin=d;
        }
        public Object clone(){
            DeepCopy obj=null;
            try {
                obj=(DeepCopy)super.clone();
            } catch (CloneNotSupportedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            obj.setBegin((Date)this.getBegin().clone());
            return obj;
        }
    }
  • 相关阅读:
    HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别
    手动部署 Ceph Mimic 三节点
    Ceph 分布式存储架构解析与工作原理
    OpenStack 的单元测试
    OpenStack 虚拟机启动流程 UML 分析(内含 UML 源码)
    我非要捅穿这 Neutron(四)Open vSwitch in Neutron
    手动部署 OpenStack Rocky 双节点
    OpenStack Blazar 架构解析与功能实践
    基于 Open vSwitch 的 OpenFlow 实践
    OpenFlow/SDN 的缘起与发展
  • 原文地址:https://www.cnblogs.com/csxf/p/3502219.html
Copyright © 2011-2022 走看看