本次讲解中我们建立一个Java的项目去体会一下序列化Serializable的使用,序列化的原理以及序列化的自定义请参见我的另外一篇博客(java高级---->Serializable序列化的源码分析)
目录导航
Serializable序列化的简要说明 Serializable序列化的代码实例 Externalizable序列化的代码实例 友情链接一、持久化的简单介绍:
“持久化”意味着对象的“生存时间”并不取决于程序是否正在执行——它存在或“生存”于程序的每一次调用之间。通过序列化一个对象,将其写入磁盘,以后在程序再次调用时重新恢复那个对象,就能圆满实现一种“持久”效果。
二、语言里增加了对象序列化的概念后,可提供对两种主要特性的支持:
远程方法调用(RMI)使本来存在于其他机器的对象可以表现出好象就在本地机器上的行为。将消息发给远程对象时,需要通过对象序列化来传输参数和返回值。 使用一个JavaBean时,它的状态信息通常在设计期间配置好。程序启动以后,这种状态信息必须保存下来,以便程序启动以后恢复;具体工作由对象序列化完成。三、Serializable的一些说明:
对象的序列化处理非常简单,只需对象实现了Serializable接口即可(该接口仅是一个标记,没有方法) 序列化的对象包括基本数据类型,所有集合类以及其他许多东西,还有Class对象 对象序列化不仅保存了对象的“全景图”,而且能追踪对象内包含的所有句柄并保存那些对象;接着又能对每个对象内包含的句柄进行追踪 使用transient关键字修饰的的变量,在序列化对象的过程中,该属性不会被序列化。四、序列化的步骤:
首先要创建某些OutputStream对象:OutputStreamoutputStream=newFileOutputStream("output.txt") 将其封装到ObjectOutputStream对象内:ObjectOutputStreamobjectOutputStream=newObjectOutputStream(outputStream); 此后只需调用writeObject()即可完成对象的序列化,并将其发送给OutputStream:objectOutputStream.writeObject(Object); 最后不要忘记关闭资源:objectOutputStream.close(),outputStream.close();五、反序列化的步骤:
首先要创建某些OutputStream对象:InputStreaminputStream=newFileInputStream("output.txt") 将其封装到ObjectInputStream对象内:ObjectInputStreamobjectInputStream=newObjectInputStream(inputStream); 此后只需调用readObject()即可完成对象的反序列化:objectInputStream.readObject(); 最后不要忘记关闭资源:objectInputStream.close(),inputStream.close();项目结构如下,源代码下载见huhx友情链接:
一、首先我们建立一个Man类,实现了Serializable接口,用于Person类的测试:
packagecom.huhx.model; importjava.io.Serializable; publicclassManimplementsSerializable{ privatestaticfinallongserialVersionUID=1L; privateStringusername; privateStringpassword; publicMan(Stringusername,Stringpassword){ this.username=username; this.password=password; } publicStringgetUsername(){ returnusername; } publicvoidsetUsername(Stringusername){ this.username=username; } publicStringgetPassword(){ returnpassword; } publicvoidsetPassword(Stringpassword){ this.password=password; } }二、我们再建立一个Person类,用于序列化:
packagecom.huhx.model; importjava.io.Serializable; publicclassPersonimplementsSerializable{ privatestaticfinallongserialVersionUID=1L; privateManman; privateStringusername; privatetransientintage; publicPerson(){ System.out.println("personconstru"); } publicPerson(Manman,Stringusername,intage){ this.man=man; this.username=username; this.age=age; } publicMangetMan(){ returnman; } publicvoidsetMan(Manman){ this.man=man; } publicStringgetUsername(){ returnusername; } publicvoidsetUsername(Stringusername){ this.username=username; } publicintgetAge(){ returnage; } publicvoidsetAge(intage){ this.age=age; } }三、编写一个包含main方法的测试类:MainTest,它的writeSerializableObject用于序列化对象:
//Serializable:把对象序列化 publicstaticvoidwriteSerializableObject(){ try{ Manman=newMan("huhx","123456"); Personperson=newPerson(man,"刘力",21); ObjectOutputStreamobjectOutputStream=newObjectOutputStream(newFileOutputStream("output.txt")); objectOutputStream.writeObject("string"); objectOutputStream.writeObject(person); objectOutputStream.close(); }catch(FileNotFoundExceptione){ e.printStackTrace(); }catch(IOExceptione){ e.printStackTrace(); } }四、测试类MainTest,它的readSerializableObject用于反序列化对象:
//Serializable:反序列化对象 publicstaticvoidreadSerializableObject(){ try{ ObjectInputStreamobjectInputStream=newObjectInputStream(newFileInputStream("output.txt")); Stringstring=(String)objectInputStream.readObject(); Personperson=(Person)objectInputStream.readObject(); objectInputStream.close(); System.out.println(string+",age:"+person.getAge()+",manusername:"+person.getMan().getUsername()); }catch(FileNotFoundExceptione){ e.printStackTrace(); }catch(Exceptione){ e.printStackTrace(); } }五、在Main方法添加以上两个方法的运行,结果如下:
在Person类中包含Man的引用,当Person被序列化的时候,从结果可以知道Man也被序列化了 writeObject方法可以传入String,是因为String首先是一个类,其次它也是实现了Serializable接口的 Person类中的age字段是transient,从打印结果可以看到,序列化Personperson=newPerson(man,"刘力",21)对象时,age没有进行序列化。如果transient修饰的Object类型的,那么打印的结果将会是null首先我们看一下Externalizable的定义:继承了Serializable接口
publicinterfaceExternalizableextendsjava.io.Serializable一、同样的我们先创建一个实现了Externalizable的User类:重写里面两个方法readExternal和writeExternal
packagecom.huhx.model; importjava.io.Externalizable; importjava.io.IOException; importjava.io.ObjectInput; importjava.io.ObjectOutput; publicclassUserimplementsExternalizable{ privateStringuser; publicStringgetUser(){ returnuser; } publicintgetAge(){ returnage; } privateintage; publicUser(){ System.out.println("userconstructor."); } publicUser(Stringuser,intage){ System.out.println("userconstructortwo."); this.user=user; this.age=age; } @Override publicvoidreadExternal(ObjectInputin)throwsIOException,ClassNotFoundException{ System.out.println("readexternal."); user=(String)in.readObject(); age=in.readInt(); } @Override publicvoidwriteExternal(ObjectOutputout)throwsIOException{ System.out.println("writeexternal."); out.writeObject(user); out.writeInt(age); } }二、在MainTest中加入方法writeExternalizableObject,用于序列化对象User
//Externalizable的序列化对象 publicstaticvoidwriteExternalizableObject(){ Useruser=newUser("huhx",22); try{ ObjectOutputStreamobjectOutputStream=newObjectOutputStream(newFileOutputStream("Externalizable.txt")); objectOutputStream.writeObject(user); objectOutputStream.close(); }catch(FileNotFoundExceptione){ e.printStackTrace(); }catch(IOExceptione){ e.printStackTrace(); } }三、在MainTest中加入方法writeExternalizableObject,用于反序列化对象User
//Externalizable的反序列化对象 publicstaticvoidreadExternalizableObject(){ try{ ObjectInputStreamobjectInputStream=newObjectInputStream(newFileInputStream("Externalizable.txt")); Useruser=(User)objectInputStream.readObject(); objectInputStream.close(); System.out.println("name:"+user.getUser()+",age:"+user.getAge()); }catch(FileNotFoundExceptione){ e.printStackTrace(); }catch(Exceptione){ e.printStackTrace(); } }四、在Main方法添加以上两个方法的运行,结果如下:
首先Useruser=newUser("huhx",22);执行了User的含参构造函数 当执行到writeObject(user);方法时,由于User实现了Externalizable接口,所以它的writeExternal会执行, 在User中的readExternal方法中调用了ObjectInput的readObject方法,在这个方法中通过反射机制创建User的实例,调用了User的无参构造函数。 然后在readObject方法执行的时候,同样会先执行User类的readExternal方法。这个会在后续源代码分析时讲到本文内容总结:Serializable序列化的简要说明,Serializable序列化的代码实例,Externalizable序列化的代码实例,友情链接,
原文链接:https://www.cnblogs.com/huhx/p/serializable.html