利用对象序列化深表克隆对象

原创 2005年04月30日 17:02:00

        在.NET上,一切都是对象。这种安排的后果之一就是在当将一个变量赋值给另一个变量的时候,会得到两个指向同一对象的变量,而不是两个不同的数据副本(除非是使用值类型而不是引用类型)。一般情况下,可以通过调用类所公开的一个特殊方法得到一个数据的副本。在.NET世界中,类应当实现ICloneable接口并公开这个接口的惟一方法Clone,让外部调用知道它能够创建类的实例的副本。框架中有多个对象可以实现这个接口,包括Array、ArrayList、BitArray、Font、Icon、Queue和Stack。

        大多数的时候,实现ICloneable接口都相当的简单。所有其他类都是从System.Object 类继承来的。该类所定义的MemberwiseClone方法可以帮助复制对象,而无需手动复制对象的各个属性:

       // Implements ICloneable.Clone 方法。

       public object Clone() 

       {

           // 对象属性如果是复杂类型,那么创建的仍然是其浅表副本。

           // 对象属性如果是复杂类型,那么复制仍然需要手动。

           // 只是利用MemberwiseClone复制所有的非对象值。

            return this.MemberwiseClone();

       }

        但是,这种方法使我们使用时感到不爽,因为,只有通过更改对象定义的源代码才可以克隆一个对象,因为MemberwiseClone方法是受保护的,它只有在类的内部才可以被访问。还有,也是在多数情况下更为重要的一个方面,MemberwiseClone方法执行的是对象的浅表复制——也就是说,它创建了对象的一个副本,但是没有创建该对象所引用的其他任何对象的副本。(就是说,对象内部的数据成员如果是引用的话,还是得我们手动复制的,如果对象图非常复杂,那么我们所面对的工作是多么的繁杂,嗷嗷不爽。)

       使用对象序列化来处理复杂的对象图可以同时解决前面所提到的两个问题。实际上,可以创建一个通用的方法来对任何对象进行深表克隆。

        这是一个简单的提供序列化克隆对象方法:

        public static object CloneObject(object obj)
        {

              // 创建内存流
              using(System.IO.MemoryStream ms = new MemoryStream(1000))
              {
                     object CloneObject;

                     // 创建序列化器(有的书称为串行器)

                     // 创建一个新的序列化器对象总是比较慢。
                     BinaryFormatter bf = new BinaryFormatter(null,
 new StreamingContext(StreamingContextStates.Clone));
                     // 将对象序列化至流

                     bf.Serialize(ms, obj);

                     // 将流指针指向第一个字符

                     ms.Seek(0, SeekOrigin.Begin);
                   

                     // 反序列化至另一个对象(即创建了一个原对象的深表副本)

                    CloneObject = bf.Deserialize(ms);

                     // 关闭流 
                     ms.Close();
                     return CloneObject;
              }
       }

以下,是一个使用这个方法克隆的例子:

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;

namespace ObjectCloneBySerialize
{

 class Class1
 {

  [STAThread]
  static void Main(string[] args)
  {
   ArrayList Persons = new ArrayList();
   Person Fangxing = new Person("Fang Xing", "Male");
   Persons.Add(Fangxing);
   Person Liwei = new Person("Li Wei", "Male");
   Persons.Add(Liwei);

   ArrayList ClonedPersons = (ArrayList)CloneObject(Persons);
   Person Zhangsan = new Person("Zhang San", "Male");
   ClonedPersons.Add(Zhangsan);

   Console.WriteLine("===== Before Clone =====");
   for(int i=0; i<Persons.Count; i++)
   {
    Person someone = (Person)Persons[i];
    Console.WriteLine(someone.Name + " " + someone.Gender);
   }
   
   Console.WriteLine("===== After Clone =====");
   for(int i=0; i<ClonedPersons.Count; i++)
   {
    Person someone = (Person)ClonedPersons[i];
    Console.WriteLine(someone.Name + " " + someone.Gender);
   }

   Console.ReadLine();

  }

  public static object CloneObject(object obj)
  {
   using(System.IO.MemoryStream ms = new MemoryStream(1000))
   {
    object CloneObject;
    BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
    bf.Serialize(ms, obj);
    ms.Seek(0, SeekOrigin.Begin);
    CloneObject = bf.Deserialize(ms);
    ms.Close();
    return CloneObject;
   }
  }
 }

 [Serializable]
 class Person
 {
  private string m_Name;
  private string m_Gender;

  public string Name
  {
   get{return m_Name;} 
  }

  public string Gender
  {
   get{return m_Gender;} 
  }

  public Person(string name, string gender)
  {
   m_Name = name;
   m_Gender = gender;
  }
 
 }
}

对象的克隆——原型模式(三):浅克隆,深克隆

7.4 带附件的周报通过引入原型模式,Sunny软件公司OA系统支持工作周报的快速克隆,极大提高了工作周报的编写效率,受到员工的一致好评。但有员工又发现一个问题,有些工作周报带有附件,例如经理助理“小...
  • will130
  • will130
  • 2016年01月12日 21:15
  • 473

java,序列化与对象克隆

写这一个是因为如果类的成员变量比较复杂,那么使用clone()方法显然不是很好 于是我们考虑了一下使用序列化对象,下面简单的讲解一下什么叫序列化对象 一种处理对象流的机制,对象流即将对象的内容流化...

Java序列化和克隆--对象深度拷贝

Java序列化和克隆--对象深度拷贝http://hi.baidu.com/en_wan/item/32bf32140b1baafcdceeca92(觉着不错所以就转来了) Java序列化和...

JAVA对象克隆和序列化

1.假克隆例子   package cloneable;   publicclass FalseCloneable { privateintid; private Stringname; public...
  • zpf336
  • zpf336
  • 2013年01月14日 21:29
  • 267

序列化与对象的克隆

什么是序列化?以下引用百度百科的解释,我以为是比较恰当的。   将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取...
  • jqncc
  • jqncc
  • 2014年02月18日 17:27
  • 616

Java对象的序列化方式克隆

简述: 用字节流的方式,复制Java对象 代码: 流克隆复制函数 public static Object deepClone(Object obj){ if(...
  • anialy
  • anialy
  • 2015年04月26日 00:30
  • 578

JSON对象克隆(JSON对象序列化)(支持function)

工作中碰到需要将JSON对象序列化保存到SessionStorage中,所以自己写了3个方法:克隆JSON对象、将JSON对象序列化保存和读取的方法。...

Java笔记(7)-输入、输出流、File类、InputStream、Reader、文件字节流、文件字符流、缓冲流、随机流、数据流、对象流、序列化和对象克隆、Scanner解析文件、Console流

Java笔记(7)-输入、输出流 字节流 字符流 文件字节流 文件字符流 缓冲流 随机流 数组流 数据流 对象流 序列化和对象克隆 文件锁 Scanner解析文件 Console就读取密码 Inp...

使用对象输入输出流(ObjectOutputStream,ObjectInputStream)实现序列化对象的深度克隆

public static T clone(T obj) throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputS...

java使用serializable进行序列化与反序列化实现对象clone(克隆)

相信很多同学都使用过serializable,相信在项目中一般你的项目经理肯定和你说过记得在你的domain的类中实现serializable,不然有时会出现一些错误。但是serializable具体...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:利用对象序列化深表克隆对象
举报原因:
原因补充:

(最多只允许输入30个字)