1.浅复制与深复制概念
⑴浅复制(浅克隆)
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不

复制它所引用的对象。

⑵深复制(深克隆)
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原

有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

2.Java的clone()方法
⑴clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:
①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象
②对任何的对象x,都有x.clone().getClass()=
=x.getClass()//克隆对象与原对象的类型一样
③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。

⑵Java中对象的克隆
①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。 
②在派生类中覆盖基类的clone()方法,并声明为public。 
③在派生类的clone()方法中,调用super.clone()。 
④在派生类中实现Cloneable接口。

请看如下代码:

class Student implements Cloneable    
{    
     String name;    
    int age;    
     Student(String name,int age)    
     {    
        this.name=name;    
        this.age=age;    
     }    
    public Object clone()    
     {    
         Object
o=null;    
        try    
         {    
        
o=(Student)super.clone();//Object 中的clone()识别出你要复制的是哪一个对象。    
         }    
        catch(CloneNotSupportedException
e)    
         {    
            
System.out.println(e.toString());    
         }    
        return o;    
     }    
}    
   
public static void main(String[] args)    
     {    
       Student s1=new
Student("zhangsan",18);    
       Student
s2=(Student)s1.clone();    
      
s2.name="lisi";    
       s2.age=20;    
      
System.out.println("name="+s1.name+","+"age="+s1.age);//修改学生2后,不影响学生1的值。    
    }

说明:
①为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。 
②继承自java.lang.Object类的clone()方法是浅复制。以下代码可以证明之。

class Professor    
{    
     String name;    
     int age;    
     Professor(String name,int age)    
     {    
        this.name=name;    
        this.age=age;    
     }    
}    
class Student implements Cloneable    
{    
     String name;// 常量对象。    
     int age;    
     Professor p;// 学生1和学生2的引用值都是一样的。    
     Student(String name,int age,Professor
p)    
     {    
        this.name=name;    
        this.age=age;    
        this.p=p;    
     }    
    public Object clone()    
     {    
         Student
o=null;    
        try    
         {    
             o=(Student)super.clone();    
         }    
        catch(CloneNotSupportedException
e)    
         {    
            
System.out.println(e.toString());    
         }    
        
o.p=(Professor)p.clone();    
        return o;    
     }    
}    
public static void main(String[] args)    
     {    
       Professor p=new
Professor("wangwu",50);    
       Student s1=new
Student("zhangsan",18,p);    
       Student
s2=(Student)s1.clone();    
      
s2.p.name="lisi";    
       s2.p.age=30;    
       System.out.println("name="+s1.p.name+","+"age="+s1.p.age);//学生1的教授成为lisi,age为30。    
}

那应该如何实现深层次的克隆,即修改s2的教授不会影响s1的教授?代码改进如下。

改进使学生1的Professor不改变(深层次的克隆)
class Professor implements Cloneable    
{    
     String name;    
     int age;    
     Professor(String name,int age)    
     {    
        this.name=name;    
        this.age=age;    
     }    
    public Object clone()    
     {    
         Object
o=null;    
        try    
         {    
            
o=super.clone();    
         }    
        catch(CloneNotSupportedException
e)    
         {    
            
System.out.println(e.toString());    
         }    
        return o;    
     }    
}    
class Student implements Cloneable    
{    
     String name;    
     int age;    
     Professor p;    
     Student(String name,int age,Professor
p)    
     {    
        this.name=name;    
        this.age=age;    
        this.p=p;    
     }    
    public Object clone()    
     {    
         Student
o=null;    
        try    
         {    
            
o=(Student)super.clone();    
         }    
        catch(CloneNotSupportedException
e)    
         {    
            
System.out.println(e.toString());    
         }    
         o.p=(Professor)p.clone();    
        return o;    
     }    
}    
public static void main(String[] args)    
     {    
       Professor p=new
Professor("wangwu",50);    
       Student s1=new
Student("zhangsan",18,p);    
       Student
s2=(Student)s1.clone();    
      
s2.p.name="lisi";    
       s2.p.age=30;    
System.out.println("name="+s1.p.name+","+"age="+s1.p.age);//学生1的教授不 改变。    
}    
3.利用串行化来做深复制
把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做 “解冻”或者“回鲜(depicking)”过程。

应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。
在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。
如下为深复制源代码。
public Object deepClone()    
{    
//将对象写到流里    
ByteArrayOutoutStream bo=new ByteArrayOutputStream();    
ObjectOutputStream oo=new ObjectOutputStream(bo);    
oo.writeObject(this);    
//从流里读出来    
ByteArrayInputStream bi=new
ByteArrayInputStream(bo.toByteArray());    
ObjectInputStream oi=new ObjectInputStream(bi);    
return(oi.readObject());    
}

这样做的前提是对象以及对象内部所有引用到的对象都是可串行化的,否则,就需要仔细考察那些不可串行化的对象可否设成transient,从而将之排除在复制过程之外。上例代码改进如下。
class Teacher implements Serializable{
String name;
int age;
Teacher(String name,int age){
this.name=name;
this.age=age;
}
}
class Student implements Serializable{
String name;//常量对象
int age;
Teacher t;//学生1和学生2的引用值都是一样的。
Student(String name,int age,Teacher t){
this.name=name;
this.age=age;
this.p=p;
}
public Object deepClone() throws IOException,
OptionalDataException,ClassNotFoundException{//将对象写到流里
ByteArrayOutoutStream bo=new ByteArrayOutputStream();
ObjectOutputStream oo=new ObjectOutputStream(bo);
oo.writeObject(this);//从流里读出来
ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi=new ObjectInputStream(bi);
return(oi.readObject());
}

}
public static void main(String[] args){ 
Teacher t=new Teacher("tangliang",30);
Student s1=new Student("zhangsan",18,t);
Student s2=(Student)s1.deepClone();
s2.t.name="tony";
s2.t.age=40;
System.out.println("name="+s1.t.name+","+"age="+s1.t.age);//学生1的老师不改变
}

Java中的深复制与浅复制的更多相关文章

  1. Java中对象的深复制和浅复制详解

    1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵ ...

  2. Java中的clone()----深复制,浅复制

    这篇文章主要介绍了Java中对象的深复制(深克隆)和浅复制(浅克隆) ,需要的朋友可以参考下 1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他 ...

  3. js中的深复制与浅复制

    前言 所谓深复制与浅复制(深拷贝与浅拷贝),乍一听感觉听高大上,像是一个非常难理解的概念,其实我们平常项目开发都是在用的,只是你可能不知道该怎么叫它的名字而已,就像你听熟了一首歌,就是不知道这首歌叫什 ...

  4. C#中的深复制与浅复制

    C#中分为值类型和引用类型,值类型的变量直接包含其数据,而引用类型的变量则存储对象的引用. 对于值类型,每个变量都有自己的数据副本,对一个变量的操作不可能影响到另一个变量.如 class Progra ...

  5. js中的深复制和浅复制

    在实际情况中经常会遇到对对象复制的问题.比如在处理项目中的一笔多结构的数据存储或者调用,这个时候你就要对对象(json)进行操作,而不同的操作根据不同的需求来定义.其中最常见最普遍的是对对象的复制,重 ...

  6. clone()方法、深复制和浅复制

    clone方法 Java中没有明确提供指针的概念和用法,而实质上没个new语句返回的都是一个指针的引用,只不过在大部分情况下开发人员不需要关心如何去操作这个指针而已. 在实际编程中,经常会遇到从某个已 ...

  7. .Net深复制、浅复制

    在.Net,大家都知道引用类型的深复制.浅复制吧. ,一般int等值类型是值类型(复制时是直接传值),一般的类(List<T>,Class)是引用类型(复制时传地址),默认是浅复制.若ob ...

  8. C++学习基础七——深复制与浅复制

    一.深复制与浅复制基本知识 深复制和浅复制,又称为深拷贝和浅拷贝. 深复制和浅复制的区别如下图1所示: 图1 图1表示的是,定义一个类CDemo,包含int a和char *str两个成员变量, 当深 ...

  9. iOS 集合的深复制与浅复制

    概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 一图以蔽之 再简单些说:浅复制就是指针拷贝:深复制 ...

随机推荐

  1. 使用StreamReader与StreamWriter进行文本文件读写

    namespace filetest { class FileUtil { public static void WriteFile(string file) { using (FileStream ...

  2. MySQL表复制

    http://www.2cto.com/database/201202/120259.html http://www.cnblogs.com/sunss/archive/2010/10/08/1845 ...

  3. Ubuntu 14.04远程登录服务器--openssh的安装和配置简明步骤

    如果要主机通过网络操作嵌入式板子,ttelnet就够了,但是 如果要相互传文件,则必须使用另外一个强大的软件SSH.更完整的步骤和截图请参考http://jingyan.baidu.com/artic ...

  4. 非索引列上的统计 <第二篇>

    非索引列上的统计 有时候,可能在连接或过滤条件中的列上没有索引.即使对这种非索引列,如果查询优化器知道这些列的数据分布(统计),它也很可能做出最佳的选择. 除了索引上的统计,SQL Server可以在 ...

  5. 符号化Symbol(符号)体系

    http://apps.hi.baidu.com/share/detail/23143648# 符号化Symbol(符号)体系 ArcGIS Engine9.3为开发人员提供了32种符号,主要分为三大 ...

  6. 我的Android进阶之旅------>Android拍照小例子

    今天简单的学习了一下android拍照的简单实现. 当然该程序是个小例子,非常简单,没有什么复杂的操作,但是可以学习到Android 拍照API流程. 1.在布局文件中添加一个 surfaceView ...

  7. 【转载】C代码优化方案

    C代码优化方案 1.选择合适的算法和数据结构2.使用尽量小的数据类型3.减少运算的强度 (1)查表(游戏程序员必修课) (2)求余运算 (3)平方运算 (4)用移位实现乘除法运算 (5)避免不必要的整 ...

  8. NavMeshAgent 动态加载障碍物

    如果你想让游戏人物绕开一些物体, 这些物体动态生成出来的.只需要给物体添加NavMeshObstacle组件即可 1. 绿色方块添加NavMeshObstacle组件 2. 红色方块没有添加NavMe ...

  9. TCP和UDP的区别(转)

    TCP协议与UDP协议的区别    首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP/IP协议与UDP协议的区别,我觉得这是没有从本质上弄清楚网络通信! ...

  10. The kth great number(set)

    The kth great number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Oth ...