对象的序列化与反序列化.ppt

上传人:桔**** 文档编号:571198287 上传时间:2024-08-09 格式:PPT 页数:41 大小:226.51KB
返回 下载 相关 举报
对象的序列化与反序列化.ppt_第1页
第1页 / 共41页
对象的序列化与反序列化.ppt_第2页
第2页 / 共41页
对象的序列化与反序列化.ppt_第3页
第3页 / 共41页
对象的序列化与反序列化.ppt_第4页
第4页 / 共41页
对象的序列化与反序列化.ppt_第5页
第5页 / 共41页
点击查看更多>>
资源描述

《对象的序列化与反序列化.ppt》由会员分享,可在线阅读,更多相关《对象的序列化与反序列化.ppt(41页珍藏版)》请在金锄头文库上搜索。

1、对象的序列化与反序列化对象的序列化与反序列化主要内容主要内容概述概述当两个进程进行远程通信时当两个进程进行远程通信时,彼此可以发送各彼此可以发送各种类型的数据种类型的数据,包括文本包括文本图片图片音频音频视频等视频等,都会以二进制序列的形式在网络上传送都会以二进制序列的形式在网络上传送.当两个当两个java进程进行通信时进程进行通信时,一个进程能否把一个进程能否把一个一个java对象发送给另一个进程呢对象发送给另一个进程呢?答案是肯定的答案是肯定的!概述概述如何才能做到呢如何才能做到呢1)发送方需要把这个发送方需要把这个java对象转换为字节序列对象转换为字节序列,才能在网上传送才能在网上传送

2、2)接收方需要把字节序列再恢复为接收方需要把字节序列再恢复为java对象对象.把把java对象转换为字节序列的过程称为对象的对象转换为字节序列的过程称为对象的序列化序列化,.把字节序列恢复为把字节序列恢复为java对象的过程称为对象的对象的过程称为对象的反序列化反序列化.序列化与反序列化序列化与反序列化对象序列化两种用途对象序列化两种用途把对象的字节序列永久的保存到硬盘上,通把对象的字节序列永久的保存到硬盘上,通常存放在一个文件中常存放在一个文件中.在网络上传送对象的字节序列在网络上传送对象的字节序列.主机1主机2文件网络传输存储到文件9.1.jdk类库中的序列化类库中的序列化API如何才能做

3、到呢如何才能做到呢1)发送方需要把这个发送方需要把这个java对象转换为字节序列对象转换为字节序列,才能在网上传送才能在网上传送2)接收方需要把字节序列再恢复为接收方需要把字节序列再恢复为java对象对象.把把java对象转换为字节序列的过程称为对象的对象转换为字节序列的过程称为对象的序列化序列化,.把字节序列恢复为把字节序列恢复为java对象的过程称为对象的对象的过程称为对象的反序列化反序列化.序列化与反序列化序列化与反序列化9.1jdk类库中的序列化类库中的序列化API java.io.ObjectOutputStream:代表对象输出流1.它的writeObject(Object obj

4、)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。Java.io.ObjectInputStream代表对象输入流,1.它的readObject()方法从一个源输入流中读取字节,再把它们反序列化成一个对象,并将其返回。9.1jdk类库中的序列化类库中的序列化API哪些类可以被序列化呢? 只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则ObjectOutputStream的writeObject(Object obj)方法会抛出IOException。实现了Serializable或Externalizable接口的类

5、也称为可序列化类。Externalizable接口继承Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为。而仅实现Serializable接口的类可以采用默认的序列化方式。Jdk的部分类 如StringDate等都实现了Serializable接口9.1jdk类库中的序列化类库中的序列化API假定一个Customer类,它的对象需要序列化。 可以有以下三种方式进行1.如果customer类仅仅实现了Serializable接口的类,那么会按照以下方式进行序列化和反序列化:ObjectOutputStream采用默认的序列化方式,对Customer

6、对象的非transient的实例变量进行序列化。ObjectInputStream采用默认的反序列化方式,对customer对象的非transient的实例变量进行反序列化。9.1jdk类库中的序列化类库中的序列化API2. 如果customer类仅仅实现了Serializable接口,并且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputStream out),那么会按照以下方式进行序列化和反序列化:ObjectOutputStream会调用Customer对象的writeObject(ObjectOutputStrea

7、m out)方法进行序列化。ObjectInputStream会调用Customer对象的readObject(ObjectInputStream in)方法进行反序列化。9.1jdk类库中的序列化类库中的序列化API3. 如果customer类实现了Externalizable接口,那么Customer类必须实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法,那么会按照以下方式进行序列化和反序列化:ObjectOutputStream会调用Customer对象的writeExternal(ObjectOutput

8、out)方法进行序列化。ObjectInputStream会调用Customer对象的readExternal(ObjectInput in)方法进行反序列化。9.1jdk类库中的序列化类库中的序列化API类框图类框图9.1jdk类库中的序列化步骤类库中的序列化步骤1.创建一个对象输出流,它可以包装一个其创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流:他类型的目标输出流,如文件输出流:ObjectOutputStream out = new ObjectOutputStream(new fileOutputStream(“D:objectfile.obj”);9.1jdk

9、类库中的序列化步骤类库中的序列化步骤2.通过对象输出流的通过对象输出流的writeObject()方法写对象,方法写对象,如:如:Out.writeObject(“hello”);Out.writeObject(new Date();9.1jdk类库中的反序列化步骤类库中的反序列化步骤1.创建一个对象输入流,它可以包装一个其创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流:他类型的源输入流,如文件输入流:ObjectInputStream in = new ObjectInputStream (new fileIutputStream(“D:objectfile.obj”);

10、9.1jdk类库中的反序列化步骤类库中的反序列化步骤2.通过对象输入流的通过对象输入流的readObject()方法读取对方法读取对象,如:象,如:String obj1=(String)in.readObject();Date obj2=(Date)in.readObject();为了能正确读取数据,必须保证向对象输为了能正确读取数据,必须保证向对象输出流写对象的顺序与从对象输入流读对象出流写对象的顺序与从对象输入流读对象的顺序一致的顺序一致例例9.1jdk类库中序列化程序类库中序列化程序1.import java.io.*;import java.util.*;2.public class

11、 ObjectSaver3. public static void main(String agrs) throws Exception 4. ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(D:objectFile.obj);5. String obj1=hello;6. Date obj2=new Date();7. Customer obj3=new Customer(Tom,20);8. /序列化对象序列化对象9. out.writeObject(obj1);10. out.writeObject(o

12、bj2);11. out.writeObject(obj3);12. out.writeInt(123);13. out.close();例例9.1jdk类库中序列化程序类库中序列化程序1./反序列化对象反序列化对象 2. ObjectInputStream in=new ObjectInputStream(new FileInputStream(D:objectFile.obj);3. String obj11 = (String)in.readObject();4. System.out.println(obj11:+obj11);5. System.out.println(obj11=o

13、bj1:+(obj11=obj1);6. Date obj22 = (Date)in.readObject();7. System.out.println(obj22:+obj22);8. System.out.println(obj22=obj2:+(obj22=obj2);9. Customer obj33 = (Customer)in.readObject();10. System.out.println(obj33:+obj33);11. System.out.println(obj33=obj3:+(obj33=obj3);12. int var= in.readInt();13.

14、System.out.println(var:+var);14. in.close();例例9.1jdk类库中序列化程序类库中序列化程序1.class Customer implements Serializable 2. private String name;3. private int age;4. 5. public Customer(String name,int age)6. this.name=name;7. this.age=age;8. 9. public String toString()return name=+name+,age=+age;10.例程例程9-2 Simp

15、leServer该服务器从命令行读取用户指定的类名,创该服务器从命令行读取用户指定的类名,创建该类的一个对象,然后向客户端两次发送建该类的一个对象,然后向客户端两次发送这个对象。这个对象。结果表明:按照默认方式序列化时,如果有结果表明:按照默认方式序列化时,如果有一个一个ObjectOutputStream对象多次序列化同一对象多次序列化同一个对象,那么有一个个对象,那么有一个ObjectInputStream对象对象反序列化出来的对象也是同一个对象。反序列化出来的对象也是同一个对象。例程例程9-2 SimpleServer1.import java.io.*;import .*;import

16、 java.util.*;2.public class SimpleServer 3. public void send(Object object)throws IOException4. ServerSocket serverSocket = new ServerSocket(8000);5. while(true)6. Socket socket=serverSocket.accept();7. OutputStream out=socket.getOutputStream();8. ObjectOutputStream oos=new ObjectOutputStream(out);9

17、. oos.writeObject(object);10. oos.writeObject(object);11. oos.close();12. socket.close();13. 例程例程9-2 SimpleServer1.public static void main(String args)throws IOException 2. Object object=null;3. if(args.length0 & args0.equals(Date)4. object=new Date();5. else if(args.length0 & args0.equals(Customer1

18、)6. object=new Customer1(Tom,1234);7. else if(args.length0 & args0.equals(Customer2)8. Customer2 customer=new Customer2(Tom);9. Order2 order1=new Order2(number1,customer);10. Order2 order2=new Order2(number2,customer);11. customer.addOrder(order1);12. customer.addOrder(order2);13. object=customer;14

19、. 例程例程9-2 SimpleServer1.else if(args.length0 & args0.equals(Customer3)2. object=new Customer3(Tom,1234);3. else if(args.length0 & args0.equals(Customer4)4. Customer4 customer=new Customer4(Tom);5. Order4 order1=new Order4(number1,customer);6. Order4 order2=new Order4(number2,customer);7. customer.ad

20、dOrder(order1);8. customer.addOrder(order2);9. object=customer;10. else if(args.length0 & args0.equals(Customer5)11. object=new Customer5(Tom,25);12. else object=Hello; 13. System.out.println(待发送的对象信息:待发送的对象信息:+object);14. new SimpleServer().send(object);例程例程9-3 SimpleClient1.import java.io.*;import

21、 .*;import java.util.*;2.public class SimpleClient 3. public void receive()throws Exception4. Socket socket = new Socket(localhost,8000);5. InputStream in=socket.getInputStream();6. ObjectInputStream ois=new ObjectInputStream(in);7. Object object1=ois.readObject();8. Object object2=ois.readObject();

22、9. System.out.println(object1);10. System.out.println(object2);11. System.out.println(object1与与object2是否为同一个对象是否为同一个对象:12. +(object1=object2); 13. public static void main(String args)throws Exception 14. new SimpleClient().receive(); 9.2实现实现Serializable接口接口ObjectOutputStream只能对实现了只能对实现了Serializable接

23、口的类的对象进行序列化,接口的类的对象进行序列化,默认情况下,默认情况下, ObjectOutputStream按照默认按照默认方式进行序列化,这种方式只能对对象的非方式进行序列化,这种方式只能对对象的非transient的实例变量进行序列化,而不会序的实例变量进行序列化,而不会序列化对象的列化对象的transient的实例变量和静态变量,的实例变量和静态变量,例如例程例如例程9-49.2实现实现Serializable接口接口1.public class Customer1 implements Serializable 2. private static int count; /用于计算用

24、于计算Customer对象的数目对象的数目3. private static final int MAX_COUNT=1000;4. private String name;5. private transient String password;6. static System.out.println(调用调用Customer1类的静态代码块类的静态代码块); 7. public Customer1()8. System.out.println(调用调用Customer1类的不带参数的构造方法类的不带参数的构造方法);9. count+; 10. public Customer1(Strin

25、g name, String password) 11. System.out.println(调用调用Customer1类的带参数的构造方法类的带参数的构造方法);12. this.name=name; this.password=password; count+; 13. public String toString() 14. return count=+count + MAX_COUNT=+MAX_COUNT 15. + name=+name + password=+ password; 9.2实现实现Serializable接口接口1.先运行先运行”java SimpleServer

26、 Customer1”,再运行命令再运行命令“java SimpleClient ”,服务器端打印的结果如下:服务器端打印的结果如下:调用调用Customer1类的静态代码块类的静态代码块调用调用Customer1类的带参数的构造方法类的带参数的构造方法待发送的对象信息:待发送的对象信息:count=1 MAX_COUNT=1000 name=Tom password=12342.客户端打印的信息(反序列化时不会调用类的构客户端打印的信息(反序列化时不会调用类的构造方法)造方法)调用调用Customer1类的静态代码块类的静态代码块count=0 MAX_COUNT=1000 name=Tom

27、 password=nullcount=0 MAX_COUNT=1000 name=Tom password=nullObject1与与Object2是否为同一个对象:是否为同一个对象:true9.2实现实现Serializable接口接口1.先运行先运行”java SimpleServer Customer1”,再运行命令再运行命令“java SimpleClient ”,服务器端打印的结果如下:服务器端打印的结果如下:调用调用Customer1类的静态代码块类的静态代码块调用调用Customer1类的带参数的构造方法类的带参数的构造方法待发送的对象信息:待发送的对象信息:count=1 M

28、AX_COUNT=1000 name=Tom password=12342.客户端打印的信息(反序列化时不会调用类的构客户端打印的信息(反序列化时不会调用类的构造方法)造方法)调用调用Customer1类的静态代码块类的静态代码块count=0 MAX_COUNT=1000 name=Tom password=nullcount=0 MAX_COUNT=1000 name=Tom password=nullObject1与与Object2是否为同一个对象:是否为同一个对象:true9.3序列化对象图序列化对象图1.类与类之间可能存在关联关系。如例程类与类之间可能存在关联关系。如例程9-5,cu

29、stomer2与与order2之间存在一对多的双向之间存在一对多的双向关联关系关联关系9.3序列化对象图序列化对象图1.public class Customer2 implements Serializable 2. private String name;3. private Set orders=new HashSet();4. static5. System.out.println(调用调用Customer2类的静态代码块类的静态代码块); 6. public Customer2()7. System.out.println(调用调用Customer2类的不带参数的构造方法类的不带参数

30、的构造方法); 8. public Customer2(String name) 9. System.out.println(调用调用Customer2类的带参数的构造方法类的带参数的构造方法);10. this.name=name; 11. 12. public void addOrder(Order2 order)13. orders.add(order); 14. public String toString() 15. String result=super.toString()+rn+orders+rn;16. return result; 9.3序列化对象图序列化对象图1.clas

31、s Order2 implements Serializable 2. private String number;3. private Customer2 customer;4. public Order2()5. System.out.println(调用调用Order2类的不带参数的构类的不带参数的构造方法造方法);6. 7. public Order2(String number,Customer2 customer)8. System.out.println(调用调用Order2类的带参数的构造类的带参数的构造方法方法);9. this.number=number;10. this.

32、customer=customer; 11. 9.3序列化对象图序列化对象图1.在例程在例程9-2中以下代码建立了他们的关联关系:中以下代码建立了他们的关联关系:2.else if(args.length0 & args0.equals(Customer2)3. Customer2 customer=new Customer2(Tom);4. Order2 order1=new Order2(number1,customer);5. Order2 order2=new Order2(number2,customer);6. customer.addOrder(order1);7. custom

33、er.addOrder(order2);8. object=customer;9. Customer2对象Order2对象Order2对象9.3序列化对象图序列化对象图1.序列化序列化customer2对象时是否会序列化与它对象时是否会序列化与它关联的对象呢?关联的对象呢?2.序列化对象时,会序列化对象序列化对象时,会序列化对象customer2以以及所有从及所有从customer2直接或间接导航到的对直接或间接导航到的对象。象。Customer2对象Order2对象Order2对象9。2。2控制序列化的行为控制序列化的行为如果用户希望控制序列化行为,可以在序列化类如果用户希望控制序列化行为,

34、可以在序列化类中提供以下方法:中提供以下方法:1.private void writeObject(ObjectOutputStream ou)在该方法中可以调用在该方法中可以调用ObjectOutputStream拥有的拥有的defaultWriteObject(ObjectOutputStream ou),使得对,使得对象输出流先执行默认的序列化操作象输出流先执行默认的序列化操作2.private void readObject(ObjectInputStream in)在该方法中同样可以调用在该方法中同样可以调用ObjectInputStream的的defaultReadObject()

35、方法。方法。9。2。2控制序列化的行为控制序列化的行为以下情况下,可以考虑用户自定义的序列以下情况下,可以考虑用户自定义的序列化方式,从而控制序列化行为:化方式,从而控制序列化行为:1.确保序列化安全性,对敏感信息加密后再确保序列化安全性,对敏感信息加密后再序列化,反序列化时需解密。序列化,反序列化时需解密。2.确保对象的成员变量符合正确的约束条件确保对象的成员变量符合正确的约束条件3.优化序列化的性能。优化序列化的性能。4.便于更好的封装类的内部数据结构,确保便于更好的封装类的内部数据结构,确保类的接口不会被类的内部实现所束缚类的接口不会被类的内部实现所束缚9.2.2控制序列化的行为控制序列

36、化的行为1.import java.io.*;2.public class Customer3 implements Serializable 3. private static int count; /用于计算用于计算Customer3对象的数目对象的数目4. private static final int MAX_COUNT=1000;5. private String name;6. private transient String password;7. 8. static System.out.println(调用调用Customer3类的静态代码块类的静态代码块); 9. pub

37、lic Customer3()10. System.out.println(调用调用Customer3类的不带参数的构造方法类的不带参数的构造方法);11. count+; 12. public Customer3(String name, String password) 13. System.out.println(调用调用Customer3类的带参数的构造方法类的带参数的构造方法);14. this.name=name;15. this.password=password;16. count+; 序列化序列化的安全的安全性性9。2。2控制序列化的行为控制序列化的行为1./* 加密数组,将

38、加密数组,将buff数组中的每个字节的每一位取反数组中的每个字节的每一位取反 2. * 例如例如13的二进制为的二进制为00001101,取反后为,取反后为111100103. */4. private byte change(byte buff)5. for(int i=0;ibuff.length;i+)6. int b=0;7. for(int j=0;jj & 1)=0 ? 1:0;9. b+=(1j)*bit;10. 11. buffi=(byte)b;12. 13. return buff;14. 9.2.2控制序列化的行为控制序列化的行为1.private void writeO

39、bject(ObjectOutputStream stream)throws IOException 2. stream.defaultWriteObject(); /先按默认方式序列化先按默认方式序列化 3. stream.writeObject(change(password.getBytes();4. stream.writeInt(count);5. 6. private void readObject(ObjectInputStream stream)7. throws IOException, ClassNotFoundException 8. stream.defaultRead

40、Object(); /先按默认方式反序列化先按默认方式反序列化9. byte buff=(byte)stream.readObject();10. password = new String(change(buff);11. count=stream.readInt();12. 9.2.2控制序列化的行为控制序列化的行为9-7public class Customer implements Serializable private int age; public Customer(int age) if(age0) /合法性检查合法性检查 throw new IllegalArgumentEx

41、ception(年龄不能小于零年龄不能小于零); this.age=age; public String toString() return age=+age; private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException stream.defaultReadObject(); /先按默认方式反序列化先按默认方式反序列化 if(age0) /合法性检查合法性检查 throw new IllegalArgumentException(年龄不能小于零年龄不能小于零); 确保对

42、象的成确保对象的成员变量符合正员变量符合正确的约束条件确的约束条件9.2.2控制序列化的行为控制序列化的行为1.public static void main(String args) throws Exception2. Customer customer = new Customer(25);3. System.out.println(Before Serialization: + customer);4. ByteArrayOutputStream buf = new ByteArrayOutputStream();5. 6. /把把Customer对象序列化到一个字节缓存中对象序列化到

43、一个字节缓存中7. ObjectOutputStream o =new ObjectOutputStream(buf);8. o.writeObject(customer);9. 10. byte byteArray=buf.toByteArray(); 11. for(int i=0;ibyteArray.length;i+)12. System.out.print(byteArrayi+ );13. if(i % 10=0 & i!=0) | i=byteArray.length-1) System.out.println();14. 确保对象的成确保对象的成员变量符合正员变量符合正确的约

44、束条件确的约束条件9.2.2控制序列化的行为控制序列化的行为 /篡改序列化数据篡改序列化数据 byteArraybyteArray.length-4=-1; byteArraybyteArray.length-3=-1; byteArraybyteArray.length-2=-1; byteArraybyteArray.length-1=-10; /从字节缓存中反序列化从字节缓存中反序列化Customer对象对象 ObjectInputStream in =new ObjectInputStream( new ByteArrayInputStream(byteArray); customer= (Customer)in.readObject();/-10 System.out.println(After Serialization: + customer); 确保对象的成确保对象的成员变量符合正员变量符合正确的约束条件确的约束条件

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号