




已阅读5页,还剩12页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
关于实现Serializable接口1、序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。简单来说序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,流的概念这里不用多说(就是I/O),我们可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间(注:要想将对象传输于网络必须进行流化)!在对对象流进行读写操作时会引发一些问题,而序列化机制正是用来解决这些问题的!它面向那些实现了Serializable接口的对象,可将它们转换成一系列字节,并可在以后完全恢复回原来的样子。这一过程亦可通过网络进行。这意味着序列化机制能自动补偿操作系统间的差异。换句话说,可以先在Windows机器上创建一个对象,对其序列化,然后通过网络发给一台Unix机器,然后在那里准确无误地重新“装配”。不必关心数据在不同机器上如何表示,也不必关心字节的顺序或者其他任何细节。2、什么情况下需要序列化 a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候; b)当你想用套接字在网络上传送对象的时候; c)当你想通过RMI传输对象的时候;3、当对一个对象实现序列化时,究竟发生了什么? 在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance ariable)比如: java 代码1. FoomyFoo=newFoo();2. myFoo.setWidth(37);3. myFoo.setHeight(70); 当通过下面的代码序列化之后,MyFoo对象中的width和Height实例变量的值(37,70)都被保存到foo.ser文件中,这样以后又可以把它 从文件中读出来,重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值,JVM还要保存一些小量信息,比如类的类型等以便恢复原来的对象。java 代码1. FileOutputStreamfs=newFileOutputStream(foo.ser);2. ObjectOutputStreamos=newObjectOutputStream(fs);3. os.writeObject(myFoo);4、实现序列化(保存到一个文件)的步骤 a)Make a FileOutputStream java 代码1. FileOutputStreamfs=newFileOutputStream(foo.ser); b)Make a ObjectOutputStream java 代码1. ObjectOutputStreamos=newObjectOutputStream(fs); c)write the objectjava 代码1. os.writeObject(myObject1);2. os.writeObject(myObject2);3. os.writeObject(myObject3); d) close the ObjectOutputStreamjava 代码1. os.close();5、举例说明java 代码1. importjava.io.*;2. 3. publicclassBoximplementsSerializable4. 5. privateintwidth;6. privateintheight;7. 8. publicvoidsetWidth(intwidth)9. this.width=width;10. 11. publicvoidsetHeight(intheight)12. this.height=height;13. 14. 15. publicstaticvoidmain(Stringargs)16. BoxmyBox=newBox();17. myBox.setWidth(50);18. myBox.setHeight(30);19. 20. try21. FileOutputStreamfs=newFileOutputStream(foo.ser);22. ObjectOutputStreamos=newObjectOutputStream(fs);23. os.writeObject(myBox);24. os.close();25. catch(Exceptionex)26. ex.printStackTrace();27. 28. 29. 30. 6、相关注意事项a)序列化时,只对对象的状态进行保存,而不管对象的方法;b)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;c)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;d)并非所有的对象都可以序列化,至于为什么不可以,有很多原因了,比如: 1.安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行RMI传输 等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的。 2. 资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现。序列化概述 简单来说序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,流的概念这里不用多说(就是I/O),我们可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间(注:要想将对象传输于网络必须进行流化)!在对对象流进行读写操作时会引发一些问题,而序列化机制正是用来解决这些问题的!问题的引出:如上所述,读写对象会有什么问题呢?比如:我要将对象写入一个磁盘文件而后再将其读出来会有什么问题吗?别急,其中一个最大的问题就是对象引用!举个例子来说:假如我有两个类,分别是A和B,B类中含有一个指向A类对象的引用,现在我们对两个类进行实例化 A a = new A(); B b = new B(); ,这时在内存中实际上分配了两个空间,一个存储对象a,一个存储对象b,接下来我们想将它们写入到磁盘的一个文件中去,就在写入文件时出现了问题!因为对象b包含对对象a的引用,所以系统会自动的将a的数据复制一份到b中,这样的话当我们从文件中恢复对象时(也就是重新加载到内存中)时,内存分配了三个空间,而对象a同时在内存中存在两份,想一想后果吧,如果我想修改对象a的数据的话,那不是还要搜索它的每一份拷贝来达到对象数据的一致性,这不是我们所希望的!以下序列化机制的解决方案:1.保存到磁盘的所有对象都获得一个序列号(1, 2, 3等等)2.当要保存一个对象时,先检查该对象是否被保存了。3.如果以前保存过,只需写入与已经保存的具有序列号x的对象相同的标记,否则,保存该对象通过以上的步骤序列化机制解决了对象引用的问题!序列化的实现 将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。package serializable;import java.io.Serializable;public class Employee implements Serializable private String name;private double salary;public Employee(String name, double salary) super();/ TODO Auto-generated constructor = name;this.salary = salary;public void raiseSalary(double byPercent)double temp = salary * byPercent / 100;salary += temp;public String toString() / TODO Auto-generated method stubreturn getClass().getName() + Name = + name + , salary = + salary +;package serializable;public class Manager extends Employee private Employee secretary;public Manager(String name, double salary) super(name, salary);/ TODO Auto-generated constructor stubsecretary = null;public Employee getSecretary() return secretary;public void setSecretary(Employee secretary) this.secretary = secretary;public String toString() / TODO Auto-generated method stubreturn super.toString() + secretary = + secretary +;package serializable;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;public class Test public static void main(String args)Employee employee = new Employee(LiLei, 1000);Manager manager1 = new Manager(Jim, 20000);manager1.setSecretary(employee);Employee staff = new Employee2;staff0 = employee;staff1 = manager1;tryObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(employee.dat);oos.writeObject(staff);oos.close();ObjectInputStream ois = new ObjectInputStream(new FileInputStream(employee.dat);Employee newStaff = (Employee)ois.readObject();ois.close();newStaff0.raiseSalary(1000);for(int i=0; i 0) next = new Worm(i, (char)(x + 1); Worm() System.out.println( Default constructor ); public String toString() String s = : + c + ( ; for(int i = 0; i d.length; i+) s += di.toString(); s += ) ; if(next != null) s += next.toString(); return s; public static void main(String args) Worm w = new Worm(6, a ); System.out.println( w = + w); try ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream( worm.out ); out.writeObject( Worm storage ); out.writeObject(w); out.close(); / Also flushes output ObjectInputStream in = new ObjectInputStream( new FileInputStream( worm.out ); String s = (String)in.readObject(); Worm w2 = (Worm)in.readObject(); System.out.println(s + , w2 = + w2); catch(Exception e) e.printStackTrace(); try ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bout); out.writeObject( Worm storage ); out.writeObject(w); out.flush(); ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( bout.toByteArray(); String s = (String)in.readObject(); Worm w3 = (Worm)in.readObject(); System.out.println(s + , w3 = + w3); catch(Exception e) e.printStackTrace(); 1、序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。2、什么情况下需要序列化 a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候; b)当你想用套接字在网络上传送对象的时候; c)当你想通过RMI传输对象的时候;3、当对一个对象实现序列化时,究竟发生了什么? 在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance ariable)比如: java 代码1. FoomyFoo=newFoo();2. myFoo.setWidth(37);3. myFoo.setHeight(70); 当通过下面的代码序列化之后,MyFoo对象中的width和Height实例变量的值(37,70)都被保存到foo.ser文件中,这样以后又可以把它从文件中读出来,重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值,JVM还要保存一些小量信息,比如类的类型等以便恢复原来的对象。java 代码1. FileOutputStreamfs=newFileOutputStream(foo.ser);2. ObjectOutputStreamos=newObjectOutputStream(fs);3. os.writeObject(myFoo);当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。把Java对象转换为字节序列的过程称为对象的序列化。把字节序列恢复为Java对象的过程称为对象的反序列化。对象的序列化主要有两种用途:1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;2) 在网络上传送对象的字节序列。一 JDK类库中的序列化APIjava.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。、只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以采用默认的序列化方式。对象序列化包括如下步骤:1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;2) 通过对象输出流的writeObject()方法写对象。对象反序列化的步骤如下:1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;2) 通过对象输入流的readObject()方法读取对象。下面让我们来看一个对应的例子,类的内容如下:import java.io.*;import java.util.Date;public class ObjectSaver public static void main(String args) throws Exception ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(D:objectFile.obj);/序列化对象Customer customer = new Customer(阿蜜果, 24);out.writeObject(你好!);out.writeObject(new Date();out.writeObject(customer);out.writeInt(123); /写入基本类型数据out.close();/反序列化对象ObjectInputStream in = new ObjectInputStream(new FileInputStream(D:objectFile.obj);System.out.println(obj1= + (String) in.readObject();System.out.println(obj2= + (Date) in.readObject();Customer obj3 = (Customer) in.readObject();System.out.println(obj3= + obj3);int obj4 = in.readInt();System.out.println(obj4= + obj4);in.close();class Customer implements Serializable private String name;private int age;public Customer(String name, int age) = name;this.age = age;public String toString() return name= + name + , age= + age;输出结果如下:obj1=你好!obj2=Sat Sep 15 22:02:21 CST 2007obj3=name=阿蜜果, age=24obj4=123因此例比较简单,在此不再详述。二实现Serializable接口ObjectOutputStream只能对Serializable接口的类的对象进行序列化。默认情况下,ObjectOutputStream按照默认方式序列化,这种序列化方式仅仅对对象的非transient的实例变量进行序列化,而不会序列化对象的transient的实例变量,也不会序列化静态变量。当ObjectOutputStream按照默认方式反序列化时,具有如下特点:1)如果在内存中对象所属的类还没有被加载,那么会先加载并初始化这个类。如果在classpath中不存在相应的类文件,那么会抛出ClassNotFoundException;2) 在反序列化时不会调用类的任何构造方法。如果用户希望控制类的序列化方式,可以在可序列化类中提供以下形式的writeObject()和readObject()方法。private void writeObject(java.io.ObjectOutputStream out) throws IOExceptionprivate void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;当ObjectOutputStream对一个Customer对象进行序列化时,如果该对象具有writeObject()方法,那么就会执行这一方法,否则就按默认方式序列化。在该对象的writeObjectt()方法中,可以先调用ObjectOutputStream的defaultWriteObject()方法,使得对象输出流先执行默认的序列化操作。同理可得出反序列化的情况,不过这次是defaultReadObject()方法。有些对象中包含一些敏感信息,这些信息不宜对外公开。如果按照默认方式对它们序列化,那么它们的序列化数据在网络上传输时,可能会被不法份子窃取。对于这类信息,可以对它们进行加密后再序列化,在反序列化时则需要解密,再恢复为原来的信息。默认的序列化方式会序列化整个对象图,这需要递归遍历对象图。如果对象图很复杂,递归遍历操作需要消耗很多的空间和时间,它的内
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 护士职业规划课件
- 薪酬增长与家庭福利-洞察及研究
- 生物多样性协同-洞察及研究
- 技术工具支持下的英语读写任务创新与实践
- 景德镇陶瓷大学《城乡历史文化遗产保护与利用》2023-2024学年第二学期期末试卷
- 内审培训考核题目及答案
- 新型生产力在农业领域的创新发展潜力
- 南阳中考美术题目及答案
- 纳税实务资料题目及答案
- 惠州学院《跨文化与国际传播》2023-2024学年第二学期期末试卷
- 人工肝治疗指南课件
- 2021年新教材人教A版高中数学必修第一册第五章三角函数 教学课件
- 掘进机整机出厂检验报告
- 最新版中小学校服选用自查整改报告
- 旅行社的导游管理制度
- DB4201∕T 645-2021 房地产经纪服务规范
- 拨叉综合课程设计
- 压铸件QC工程图
- 常用标准波导和法兰尺寸
- pH 值对柠檬酸缓凝效果影响的研究
- 705型试验台技术条件及说明书
评论
0/150
提交评论