本章关注对象序列化API,它提供了一个框架,用来将对象编码成字节流,并从字节流中重新构建对象。“将对象编码成字节流”被称作对象序列化,相反的处理过程被称作反序列化。序列化技术为远程通信提供了标准的线路级对象表示法,也为JavaBeans组件结构提供了标准的持久化数据格式。
第七十四条:谨慎地实现Serializable接口
实现Serializable接口而付出的最大代价是,一旦一个类发布,就大大降低了“改变这个类实现”的灵活性。序列化会使类的演变受到限制,这与流的唯一标识符有关,通常它也被称为序列版本UID。每个可序列化的类都有一个唯一标识符与它相关联。如果你没有显示指定该标志号,系统就会自动根据这个类的名称,所实现接口的名称等计算出一个标志号。如果你改变了类,比如增加了一个工具方法,自动产生的UID会产生变化。因此,如果你没有显示声明UID,兼容性将遭到破坏。
第二个代价是,它增加了出现Bug和安全漏洞的可能性。序列化机制是一种语言之外的对象创建机制。反序列化是一个隐藏的构造器,具备和其他构造器相同的特点。所以要确保:反序列化过程必须要保证所有“由真正的构造器建立起来的约束关系”,并且不允许攻击者访问正在构造过程中的对象的内部信息。依靠默认的反序列化机制,很容易使对象的约束关系遭到破坏,以及遭到非法访问。
第三个代价,随着类发行新的版本,相关的测试负担也增加了。
根据经验,比如Date和BigInteger这样的值类应该实现Serializable,大多数的集合也应如此。代表活动实体的类比如线程池,一般不实现。
第七十五条:考虑使用自定义的序列化形式
如果一个对象的物理表示法等同于它的逻辑内容,可能就适合使用默认的序列化形式。即使你确认了默认的序列化形式是合适的,通常还必须提供一个readObject方法以保证约束关系和安全性。
当一个对象的物理表示法和逻辑数据内容有实质性的区别时,使用默认序列化形式会有下面四个缺点:
1.它使这个类的导出API永远的束缚在该类的内部表示法上。
2.消耗过多的空间。
3.消耗过多的时间。
4.引起栈溢出。
自定义序列化形式通常自定义writeObject和readObject方法,用来序列化和反序列化。同时,使用transient修饰符使实例域从一个类的默认序列化形式中省略掉。
第七十六条:保护性的编写readObject方法
不严格地说,readObject是一个“用字节流作为唯一参数”的构造器。在正常使用的情况下,对一个正常构造的实例进行序列化可以产生字节流。但是,当面对一个人工仿造的字节流时,readObject产生的对象可能会违反所属的类的约束条件。
为了解决这个问题,可以为实现默认序列化的类添加一个readObject方法,该方法首先调用defaultReadObject,然后检查被反序列化之后对象的有效性。但这样仍可能解决不了问题,攻击者可以使用对象引用来修改实例的内部组件。当一个对象被反序列化的时候,对于客户端不应该拥有的对象应用,如果哪个域包含了这样的对象引用,就必须要做保护性拷贝。并且,保护性拷贝是在有效性检查之前进行。
下面的建议有利于编写更加健壮的readObject方法:
1.对于对象引用域必须保持为私有的类,要保护性地拷贝这些域中的每个对象。不可变类的可变组件就属于这一类别。
2.对于任何约束条件,如果检查失败,抛出InvalidObjectException异常。这些检查跟在所有保护性拷贝之后。
3.如果整个对象在被反序列化之后必须进行验证,就应该使用ObjectInputValidation接口
4.不要调用类中可能被覆盖的方法。
第七十七条:对于实例控制,枚举类型优先于readResolve
readResolve特性允许你用readObject创建的实例代替另一个实例。对于一个正在被反序列化的对象,如果他的类定义了一个readResolve方法,并且具备正确的声明,那么在反序列化之后,新建对象上的readResolve方法就会被调用。然后该方法返回的对象引用被返回,取代新建的对象。
尽可能使用枚举类型来实施实例控制的约束条件。如果做不到,同时又需要一个既可序列化又是实例受控的类,就必须提供一个readResolve方法,并确保该类的所有实例域都为基本类型或者是transient的。
第七十八条:考虑用序列化代理代替序列化实例
序列化代理模式相当简单。首先,为可序列化的类设计一个私有的静态嵌套类,精确地表示外围类的实例的逻辑状态。这个嵌套类被称作序列化代理,它应该有一个单独的构造器,其参数类型就是那个外围类。这个构造器只从它的参数中复制数据:他不需要进行任何一致性检查或者保护性拷贝。从设计的角度看,序列化代理的默认序列化形式是外围类最好的序列化形式。外围类及其序列代理都必须声明Serializable接口。
相关推荐
什么叫反序列化? 就是再把介质中的东西还原成对象,把石子还原成人的过程。 在进行这些操作的时候都需要这个可以被序列化,要能被序列化,就得给类头加[Serializable]特性。 通常网络程序为了传输安全才这么做。不...
java 对象的序列化与反序列化 java 对象的序列化与反序列化
[{"listA":[{"id":"fds","name":"张三"},{"id":"fds","name":"李四"}],"test":"432"}, {"listA":[{"id":"fds","name":"张三"},{"id":"fds","name":"李四"}],...数组里面封装数组的反序列化方法,通过两个bean,进行封装
Vbs序列化/反序列化Json基类 可直接使用,bug已被我修复 Example: Dim fso, json, str, o, i Set json = New VbsJson Set fso = WScript.CreateObject("Scripting.Filesystemobject") str = fso.OpenTextFile(...
C++ JSON 序列化与反序列化 相关的博客文章见:http://blog.csdn.net/TragicGuy
序列化和反序列化的封装类,只要调用就行 序列化和反序列化的封装类 序列化和反序列化的封装类 序列化和反序列化的封装类 序列化和反序列化的封装类
Xson是一个Java对象序列化和反序列化程序。支持Java对象到字节数组的序列化,和从字节数组到Java对象的反序列化。 Maven: <groupId>com.github.xsonorg</groupId> <artifactId>xson-core <version>1.0.1 ...
C# xml序列化及反序列化(解析xml为对象及对象转xml保存),方法一反序列化取节点KV值,方法二反序列化取节点标签值,方法三取节点KV值,并增加节点对象数组及节点标签组合反序列化
java反序列化工具,覆盖jboss、weblogic、websphere。
jackson json序列化 json反序列化 jar包 直接下载拷贝到项目中buildpath即可使用
序列化和反序列化dll文件和proto
序列化和反序列化实例 序列化和反序列化实例 窗体实例 序列化和反序列化实例 序列化和反序列化实例 序列化和反序列化实例 序列化和反序列化实例
delphi_JSON序列化反序列化
大数据场景下序列化和反序列化技术,谷歌提供技术 protobuf-jetbrains-plugin-0.13.0.zip
json 反序列化 http://blog.csdn.net/walker02/article/details/8105936
序列化反序列化例题net 序列化反序列化例题net 序列化反序列化例题net
Unity 中使用Protobuf进行序列化和反序列化的Demo
所有在反序列化Json字符串时需要一种通用的转换方式,而不是写死的某个类的反序列化,这里介绍的一种思路就是使用dynamic关键字来实现通用反序列化并比较反序列化后的对象是否深度相等即比较对象的各个字段是否相等...
java序列化和反序列化java序列化和反序列化java序列化和反序列化
通过反序列化,解析Xml文件。非常简单的例子,自己留用