在以前的工作中经常涉及到java对象序列化/反序列化进行网络数据传输,虽然项目中使用过,但对java序列化的概念还是比较模糊,今天写下一篇文章,作为对之前欠下的知识记录。
序列化Serialization:是一种将对象以一连串的字节描述的过程;反序列化deserialization是一种将这些字节重建成一个对象的过程.
序列化 的应用:
1、永久性保存对象,保存对象的字节序列到本地文件中。
2、 通过序列化对象在网络中传递对象;
3、通过序列化在进程间传递对象。
在java中默认使用Serializable接口实现对象的序列化,对于所有的非static,transient(瞬态)的field进行序列化/反序列化操作。所有实现Serializable序列化接口类最好自动生成序列号(serialVersionUID)。
序列号的值有两种:一种是默认的1L,另一种是根据当前类中定义的field和方法生成的64位的数值。 序列号的生成与jvm,类字段,类的方法的定义有关,如果不为需要序列化的类设置序列号,被序列化的文件或是网络传输的消息,在反序列化的过程中,可能由于反序列化端生成的序列号发生变化而导致反序列化失败。
因此为了保证我们序列化的数据可以正确的被反序列化,强烈建议创建序列化的类的时候创建序列号。序列号的主要用途是进行版本的管理,对于具有相同版本号的对象是可以进行数据的序列化和反序列化的,对于不同版本号的数据时无法进行的。在实际的使用过程中,我们的模型是需要具有向上和向下兼容的能力,例如对于老系统持久化的数据可以平滑的在新系统下使用,而对于新系统持久化的数据也可以在老系统中继续使用。
在具有相同序列号数据的反序列化过程中,对于不存在的字段自动忽略,对于存在的字段自动进行反序列化的过程。
序列化注意事项:
1)序列化时,只对对象的状态进行保存,而不管对象的方法;
3)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
4)并非所有的对象都可以序列化,,至于为什么不可以,有很多原因了,比如:
1.安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行rmi传输 等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的。
2. 资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分 配,而且,也是没有必要这样实现。
5)不建议内部类进行序列化,因为内部类可以获取外部类的所有的属性字段,即内部类存有外部类的引用,如果外部不能够进行序列化,将导致内部类序列化失败;当将内部类声明为static的时候,由于内部类不再保存有外部类的引用,因此内部类可以进行序列化。
6)java序列化的过程不仅存储了需要序列化的字段信息,还会存储一些额外的信息帮助反序列化。因此可以通过定义private void readObject(InputStream)和private void writeObject(OutStream)的方式自定义对象的序列化和反序列化过程。注意自定义序列化和反序列化的过程,操作需要成对出现,如果操作的顺序不正确将会导致反序列化失败。
第一次写学习的总结,感觉好多想要说的不知道如何表达,在java的HashMap,HashSet等集合中都实现了序列化的接口并定制有序列化的反序列的方法,感觉通过学习jdk的源码是最快,最好学习知识的方法。