一文带你彻底理解Java序列化和反序列化
Java序列化是什么?
Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复为Java对象的过程。
反序列化:客户端重文件,或者网络中获取到文件以后,在内存中重构对象。
序列化:对象序列化的最重要的作用是传递和保存对象的时候,保证对象的完整性和可传递性。方便字节可以在网络上传输以及保存在本地文件。
为什么需要序列化和反序列化
实现分布式
核心在于RMI,可以利用对象序列化运行远程主机上的服务,实现运行的时候,就像在本地上运行Java对象一样。
实现递归保存对象
进行序列化的时候,单单并不是保存一个对象,而是递归的保存一整个对象序列,即递归保存,通过反序列化,可以递归的得到一整个对象序列。
序列信息可以永久保存
用于序列化的信息,可以永久保存为文件,或者保存在数据库中,在使用的时候,再次随时恢复到内存中,实现内存中的类的信息可以永久的保存。
数据格式统一
比照Linux的一切皆文件的思想,同时Java也是这样的思想,让数据格式尽可能的统一,让对象,文件,数据,等等许许多多不同的格式,都让其统一,以及保存。实现数据可以完整的传输和保存。然后进行反序列化还原,即,对象还是对象,文件还是文件。
实现Java序列化和反序列化
要进行反序列化需要实现一个接口。即Serializabei接口。
代码如下
需要转化的类
packagecommon.lang; importjava.io.Serializable; importorg.apache.commons.lang3.builder.ToStringBuilder; importorg.apache.commons.lang3.builder.ToStringStyle; publicclassUser1implementsSerializable{ privateStringname; privateintage; publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } publicintgetAge(){ returnage; } publicvoidsetAge(intage){ this.age=age; } @Override publicStringtoString(){ returnnewToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) .append("name",name) .append("age",age) .toString(); } }
进行序列化,以及反序列化
packagecommon.lang; importjava.io.File; importjava.io.FileInputStream; importjava.io.FileNotFoundException; importjava.io.FileOutputStream; importjava.io.IOException; importjava.io.ObjectInputStream; importjava.io.ObjectOutputStream; publicclassSerializableDemo1{ publicstaticvoidmain(String[]args)throwsException,IOException{ //初始化对象 User1user=newUser1(); user.setName("yaomy"); user.setAge(23); System.out.println(user); //序列化对象到文件中 ObjectOutputStreamoos=newObjectOutputStream(newFileOutputStream("template")); oos.writeObject(user); oos.close(); //反序列化 Filefile=newFile("template"); ObjectInputStreamois=newObjectInputStream(newFileInputStream(file)); User1newUser=(User1)ois.readObject(); System.out.println(newUser.toString()); } }
另一个序列化接口Externalizable
继续实现Externalizable接口
packagecommon.lang; importjava.io.Externalizable; importjava.io.IOException; importjava.io.ObjectInput; importjava.io.ObjectOutput; importorg.apache.commons.lang3.builder.ToStringBuilder; importorg.apache.commons.lang3.builder.ToStringStyle; publicclassUser1implementsExternalizable{ privateStringname; privateintage; publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } publicintgetAge(){ returnage; } publicvoidsetAge(intage){ this.age=age; } @Override publicStringtoString(){ returnnewToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) .append("name",name) .append("age",age) .toString(); } @Override publicvoidwriteExternal(ObjectOutputout)throwsIOException{ //TODOAuto-generatedmethodstub } @Override publicvoidreadExternal(ObjectInputin)throwsIOException,ClassNotFoundException{ //TODOAuto-generatedmethodstub } }
进行序列化以及反序列化
packagecommon.lang; importjava.io.File; importjava.io.FileInputStream; importjava.io.FileNotFoundException; importjava.io.FileOutputStream; importjava.io.IOException; importjava.io.ObjectInputStream; importjava.io.ObjectOutputStream; publicclassSerializableDemo1{ publicstaticvoidmain(String[]args)throwsException,IOException{ //初始化对象 User1user=newUser1(); user.setName("yaomy"); user.setAge(23); System.out.println(user); //序列化对象到文件中 ObjectOutputStreamoos=newObjectOutputStream(newFileOutputStream("template")); oos.writeObject(user); oos.close(); //反序列化 Filefile=newFile("template"); ObjectInputStreamois=newObjectInputStream(newFileInputStream(file)); User1newUser=(User1)ois.readObject(); System.out.println(newUser.toString()); ois.close(); } }
查看输出的结构
common.lang.User1@6ef64f64[
name=yaomy
age=23
]
common.lang.User1@184c9860[
name=
age=0
]
根据输出的结果可以看到,对User1进行序列化然后再反序列化之后对象的属性都恢复成了默认值,即,之前那个对象的状态没有被持久保存下来,这就是Externalization和Serialization接口的区别,其中前者接口会被恢复成为默认值,后者接口不会恢复默认值。
如果需要恢复,这里就需要重写两个抽象方法,分别是writeExternal与readExternal两个抽象方法。
packagecommon.lang; importjava.io.Externalizable; importjava.io.IOException; importjava.io.ObjectInput; importjava.io.ObjectOutput; importorg.apache.commons.lang3.builder.ToStringBuilder; importorg.apache.commons.lang3.builder.ToStringStyle; publicclassUser1implementsExternalizable{ privateStringname; privateintage; publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } publicintgetAge(){ returnage; } publicvoidsetAge(intage){ this.age=age; } @Override publicStringtoString(){ returnnewToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) .append("name",name) .append("age",age) .toString(); } @Override publicvoidwriteExternal(ObjectOutputout)throwsIOException{ out.writeObject(name); out.writeInt(age); } @Override publicvoidreadExternal(ObjectInputin)throwsIOException,ClassNotFoundException{ name=(String)in.readObject(); age=in.readInt(); } }
packagecommon.lang; importjava.io.File; importjava.io.FileInputStream; importjava.io.FileNotFoundException; importjava.io.FileOutputStream; importjava.io.IOException; importjava.io.ObjectInputStream; importjava.io.ObjectOutputStream; publicclassSerializableDemo1{ publicstaticvoidmain(String[]args)throwsException,IOException{ //初始化对象 User1user=newUser1(); user.setName("yaomy"); user.setAge(23); System.out.println(user); //序列化对象到文件中 ObjectOutputStreamoos=newObjectOutputStream(newFileOutputStream("template")); oos.writeObject(user); oos.close(); //反序列化 Filefile=newFile("template"); ObjectInputStreamois=newObjectInputStream(newFileInputStream(file)); User1newUser=(User1)ois.readObject(); System.out.println(newUser.toString()); ois.close(); } }
输出的结果
common.lang.User1@6cd66725[
name=yaomy
age=23
]
common.lang.User1@19160e64[
name=yaomy
age=23
]
静态变量的序列化
实例
publicclassTestimplementsSerializable{ privatestaticfinallongserialVersionUID=1L; publicstaticintstaticVar=5; publicstaticvoidmain(String[]args){ try{ //初始时staticVar为5 ObjectOutputStreamout=newObjectOutputStream( newFileOutputStream("result.obj")); out.writeObject(newTest()); out.close(); //序列化后修改为10 Test.staticVar=10; ObjectInputStreamoin=newObjectInputStream(newFileInputStream( "result.obj")); Testt=(Test)oin.readObject(); oin.close(); //再读取,通过t.staticVar打印新的值 System.out.println(t.staticVar); }catch(FileNotFoundExceptione){ e.printStackTrace(); }catch(IOExceptione){ e.printStackTrace(); }catch(ClassNotFoundExceptione){ e.printStackTrace(); } } }
代码阐述一下过程,在main方法中,对象序列化以后,修改静态变量的数值,再把序列化后的对象读取出来,此时输出的值为10.
理解如下:打印的staticVar是从读取对象里获得的,打印10的原因是因为序列化时,不保存静态变量,只保存内存中的状态。此时修改静态变量的值,修改的是类中的值,输出的也是类中的值,和内存无关。
Transient关键字
Transient关键字,加上以后,可以阻止该变量被序列化到文件中,反序列化以后,变量的值设定为初始值。
以上就是一文带你彻底理解Java序列化和反序列化的详细内容,更多关于Java序列化和反序列化的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。