对象的序列化与反序列化主要内容概述•当两个进程进行远程通信时,彼此可以发送各种类型的数据,包括文本\图片\音频\视频等,都会以二进制序列的形式在网络上传送.•当两个java进程进行通信时,一个进程能否把一个java对象发送给另一个进程呢?答案是肯定的!概述•如何才能做到呢•1)发送方需要把这个java对象转换为字节序列,才能在网上传送•2)接收方需要把字节序列再恢复为java对象.•把java对象转换为字节序列的过程称为对象的序列化,.•把字节序列恢复为java对象的过程称为对象的反序列化.序列化与反序列化对象序列化两种用途•把对象的字节序列永久的保存到硬盘上,通常存放在一个文件中.•在网络上传送对象的字节序列.主机1主机2文件网络传输存储到文件9.1.jdk类库中的序列化API•如何才能做到呢•1)发送方需要把这个java对象转换为字节序列,才能在网上传送•2)接收方需要把字节序列再恢复为java对象.•把java对象转换为字节序列的过程称为对象的序列化,.•把字节序列恢复为java对象的过程称为对象的反序列化.序列化与反序列化9.1jdk类库中的序列化API•java.io.ObjectOutputStream:代表对象输出流1.它的writeObject(Objectobj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。•Java.io.ObjectInputStream代表对象输入流,1.它的readObject()方法从一个源输入流中读取字节,再把它们反序列化成一个对象,并将其返回。9.1jdk类库中的序列化API•哪些类可以被序列化呢?•只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则ObjectOutputStream的writeObject(Objectobj)方法会抛出IOException。•实现了Serializable或Externalizable接口的类也称为可序列化类。•Externalizable接口继承Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为。而仅实现Serializable接口的类可以采用默认的序列化方式。•Jdk的部分类如String\Date等都实现了Serializable接口9.1jdk类库中的序列化API•假定一个Customer类,它的对象需要序列化。可以有以下三种方式进行1.如果customer类仅仅实现了Serializable接口的类,那么会按照以下方式进行序列化和反序列化:•ObjectOutputStream采用默认的序列化方式,对Customer对象的非transient的实例变量进行序列化。•ObjectInputStream采用默认的反序列化方式,对customer对象的非transient的实例变量进行反序列化。9.1jdk类库中的序列化API2.如果customer类仅仅实现了Serializable接口,并且还定义了readObject(ObjectInputStreamin)和writeObject(ObjectOutputStreamout),那么会按照以下方式进行序列化和反序列化:•ObjectOutputStream会调用Customer对象的writeObject(ObjectOutputStreamout)方法进行序列化。•ObjectInputStream会调用Customer对象的readObject(ObjectInputStreamin)方法进行反序列化。9.1jdk类库中的序列化API3.如果customer类实现了Externalizable接口,那么Customer类必须实现readExternal(ObjectInputin)和writeExternal(ObjectOutputout)方法,那么会按照以下方式进行序列化和反序列化:•ObjectOutputStream会调用Customer对象的writeExternal(ObjectOutputout)方法进行序列化。•ObjectInputStream会调用Customer对象的readExternal(ObjectInputin)方法进行反序列化。9.1jdk类库中的序列化API类框图9.1jdk类库中的序列化步骤1.创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流:•ObjectOutputStreamout=newObjectOutputStream(newfileOutputStream(“D:\\objectfile.obj”));9.1jdk类库中的序列化步骤2.通过对象输出流的writeObject()方法写对象,如:•Out.writeObject(“hello”);•Out.writeObject(newDate());9.1jdk类库中的反序列化步骤1.创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流:•ObjectInputStreamin=newObjectInputStream(newfileIutputStream(“D:\\objectfile.obj”));9.1jdk类库中的反序列化步骤2.通过对象输入流的readObject()方法读取对象,如:•Stringobj1=(String)in.readObject();•Dateobj2=(Date)in.readObject();•为了能正确读取数据,必须保证向对象输出流写对象的顺序与从对象输入流读对象的顺序一致例9.1jdk类库中序列化程序1.importjava.io.*;importjava.util.*;2.publicclassObjectSaver{3.publicstaticvoidmain(Stringagrs[])throwsException{4.ObjectOutputStreamout=newObjectOutputStream(newFileOutputStream(D:\\objectFile.obj));5.Stringobj1=hello;6.Dateobj2=newDate();7.Customerobj3=newCustomer(Tom,20);8.//序列化对象9.out.writeObject(obj1);10.out.writeObject(obj2);11.out.writeObject(obj3);12.out.writeInt(123);13.out.close();例9.1jdk类库中序列化程序1.//反序列化对象2.ObjectInputStreamin=newObjectInputStream(newFileInputStream(D:\\objectFile.obj));3.Stringobj11=(String)in.readObject();4.System.out.println(obj11:+obj11);5.System.out.println(obj11==obj1:+(obj11==obj1));6.Dateobj22=(Date)in.readObject();7.System.out.println(obj22:+obj22);8.System.out.println(obj22==obj2:+(obj22==obj2));9.Customerobj33=(Customer)in.readObject();10.System.out.println(obj33:+obj33);11.System.out.println(obj33==obj3:+(obj33==obj3));12.intvar=in.readInt();13.System.out.println(var:+var);14.in.close();例9.1jdk类库中序列化程序1.classCustomerimplementsSerializable{2.privateStringname;3.privateintage;4.5.publicCustomer(Stringname,intage){6.this.name=name;7.this.age=age;8.}9.publicStringtoString(){returnname=+name+,age=+age;}10.}例程9-2SimpleServer•该服务器从命令行读取用户指定的类名,创建该类的一个对象,然后向客户端两次发送这个对象。•结果表明:按照默认方式序列化时,如果有一个ObjectOutputStream对象多次序列化同一个对象,那么有一个ObjectInputStream对象反序列化出来的对象也是同一个对象。例程9-2SimpleServer1.importjava.io.*;importjava.net.*;importjava.util.*;2.publicclassSimpleServer{3.publicvoidsend(Objectobject)throwsIOException{4.ServerSocketserverSocket=newServerSocket(8000);5.while(true){6.Socketsocket=serverSocket.accept();7.OutputStreamout=socket.getOutputStream();8.ObjectOutputStreamoos=newObjectOutputStream(out);9.oos.writeObject(object);10.oos.writeObject(object);11.oos.close();12.socket.close();13.}}例程9-2SimpleServer1.publicstaticvoidmain(Stringargs[])throwsIOException{2.Objectobject=null;3.if(args.length0&&args[0].equals(Date))4.object=newDate();5.elseif(args.length0&&args[0].equals(Customer1))6.object=newCustomer1(Tom,1234);7.elseif(args.length0&&args[0].equals(Customer2)){8.Customer2customer=newCustomer2(Tom);9.Order2order1=newOrder2(number1,customer);10.Order2order2=newOrder2(number2,customer);11.customer.addOrder(order1);12.customer.addOrder(order2);13.object=customer;14.}例程9-2SimpleServer1.elseif(args.length0&&args[0].equals(Customer3)){2.object=newCustomer3(Tom,1234);3.}elseif(args.length0&&args[0].equals(Customer4)){4.Customer4customer=newCustomer4(Tom);5.Order4order1=newOrder4(number1,customer);6.Order4order2=newOrder4(number2,customer);7.customer.addOrder(order1);8.customer.addOrder(order2);9.object=customer;10.}elseif(args.length0&&args[0].equals(Customer5