??xml version="1.0" encoding="utf-8" standalone="yes"?> 要实现序列化Q则必须实现serializable或Externalizable接口。后者承自前者,两者的区别Q实现前者的cd以采用默认的序列化方式。而实现后者的cd完全pw来控制序列化的行ؓ?br />
在序列化和反序列化过E中需要特D处理的cdM用下列准签名来实现ҎҎQ?/p>
如果CustomercdCExternalizable接口Q那么Customercdd现readExternal ObjectOutputStream只能对实CSerializable接口的类的对象进行序列化。默认情况下QObjectOutputStream按照默认方式序列化,q种序列化方式仅仅对对象的非transient的实例变量进行序列化Q而不会序列化对象的transient的实例变量,也不会序列化静态变量?/p>
而当ObjectInputStream按照默认方式反序列化Ӟ有以下特点: 被transient修饰W来修饰的实例变量是不会序列化的Q一般用transient来修C下类型的的变量: Q) 实例变量不代表对象的固有的内部数据,仅仅代表h一定逻辑含义的时数据?br />
Q) 实例变量表示一些比较敏感的信息Q如密码Q出于安全方面的原因Q不希望对其序列化?br />
Q) 实例变量需要按照用戯定义的方式序列化Q如l过加密后再序列化。这q种情况下可以将其用transient修饰Q然后在writeObject()Ҏ中对其序列化?nbsp; 参见SerializableDemo中的Customer2及Order2cM间的关系?br />
当通过ObjectOutputStream对象的writeObject(customer)Ҏ序列化Customer2对象Ӟ也会序列化与它关联的Order2对象。而当通过ObjectInputStream对象的readObject()Ҏ反序列化Customer2对象Ӟ实际上会Ҏ个对象图反序列化?br />
如果对象A持有对象B的引用(注意是A持有B的引用)Q以及间接持有其他对象的引用Q则按照默认方式序列化对象AӞ会将A以及A持有的以及间接持有的所有对象都序列化。反序列化也是如此?/p>
如果用户希望控制cȝ序列化方式,可以在可序列化类中提供以下Ş式的writeObject()Ҏ和readObject()ҎQ?/p>
一般的做法是,在writeObject()Ҏ中,选留骼ObjectOutputStream的defaultWriteObject()ҎQ得对象输出流先执行默认的序列化操作?br />
反序列化Ӟ在readObject()Ҏ中,先调用ObjectInputStream的defaultReadObject()Ҏ?/p>
Externallizable接口l承自Serializable接口Q如果一个类实现了Externalizable接口Q那么将完全p个类控制自n的序列化行ؓ。Externalizable接口中声明了两个ҎQ?br />
writeExternal负责序列化操作,readExternal负责反序列化操作。在对实CExternallizable接口的类的对象进行反序列化时Q会先调用类的不带参数的构造方法,q是有别默认反序列化方式的(见2Q。所以实现Externalizable接口的类必须要有不含参数的构造方法?/p>
实例见SerializableDemo里的Customer5的两个版本。将CustomerQ?Q和SimpleServer攑֜server端,Customer2.0和SimpleClient攑֜Client端,直接q行Q将发现抛出错误Q显CZ兼容Q解军_法是手动两个Customer的serialVersionUID设ؓ同一个|q样p兼容。但是这U办法的能力很有限,当一个类的不同版本的serialVersionUID相同Q仍然有可能出现序列化不兼容的情c因为序列化兼容性不仅取决于serialVersionUIDQ还取决于类的不同版本的实现l节和序列化l节?/p>
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
writeObject Ҏ负责写入特定cȝ对象的状态,以便相应?readObject Ҏ可以q原它。通过调用 out.defaultWriteObject 可以调用保存 Object 的字D늚默认机制。该Ҏ本n不需要涉及属于其类或子cȝ状态。状态是通过使用 writeObject Ҏ或?DataOutput 支持的用于基本数据类型的Ҏ各个字D写?ObjectOutputStream 来保存的?
readObject Ҏ负责从流中读取ƈq原cdDc它可以调用 in.defaultReadObject 来调用默认机Ӟ以还原对象的非静态和非瞬态字DcdefaultReadObject Ҏ使用中的信息来分配中通过当前对象中相应命名字D保存的对象的字Dc这用于处理cd展后需要添加新字段的情形。该Ҏ本n不需要涉及属于其类或子cȝ状态。状态是通过使用 writeObject Ҏ或?DataOutput 支持的用于基本数据类型的Ҏ各个字D写?ObjectOutputStream 来保存的?nbsp;
假定有一个名为Customer的类Q它的对象需要序列化Q如果CustomercM仅实CSerializable接口的类Q那么将按照以下方式序列化及反序列化Customer对象Q?br />
如果CustomercM仅实CSerializable接口的类Qƈ且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputStream out)ҎQ那么将按照以下方式序列化及反序化Customer对象Q?
(ObjectInput in)和writeExternal(ObjectOutput out)Ҏ。在q种情况下,按照以下方式序列化及反序列化Customer对象Q?/p>
2.实现Serializable接口
Q?Q序列化对象?/h2>
Q?Q控制序列化的行?/h2>
private void writeObject java.io.ObjectOutputStream out)throws IOException
private void readObject java.io.ObjectInputStream in)throws IOException,ClassNotFoundException;
Q?QreadResolve()Ҏ在童便类中的q用
如果一个类提供了readResolve()ҎQ那么在执行反序列化操作Ӟ先按照默认方式或者用戯定义的方式进行反序列化,最后再调用readResolve()ҎQ该Ҏq回的对象ؓ反序列化的最l结果?br />
readResolve()Ҏ应该能够被类本n、同一个包中的c,或者访问,因此readResolve()Ҏ的访问权限可以是pirvate、默认或protectedU别?br />
readResolve()Ҏ用来重新指定反序列化得到的对象,与此对应QJava序列化规范还允许在可序列化类中定义一个writeReplace()ҎQ用来重新指定被序列化的对象。writeReplace()Ҏq回一个Objectcd的对象,q个q回对象才是真正要被序列化的对象。权限也可以Z上三U之一?nbsp; Q?实现Externalizalbe接口
public void writeExternal(ObjectOutput out)throws IOException
public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException
Q?可序列化cȝ不同版本的序列化兼容?/h1>
估计大家?/span>finalize()都有个基本的认识Q那是作清理资源之用。比如在cȝ某个Ҏ中打开了一个文Ӟ那么你可能需要通过finalize()Ҏ来释放该资源。但是话说回来,java世界里,一切皆对象Q而Q何一个学java的h都知道,java对象是不需要手动去清理的,因ؓjava有强大的垃圾回收器,有h可能会有疑问Q那既然如此Qؓ什么还需要在finalize()中手动释放资源呢Q当Ӟ面对q一问题Q有很好的理由去解释Q因源是有限的,而我们又知道垃圾回收器的U程优先U非怽Q在g得以的情况下Q它才会工作Q也是_只要内存_Q失效的对象׃会被清理Q它所持有的资源也得不到释放Q而资源又是有限的Q比如数据库q接Q所以需要我们去手动释放。不q这一点,?/span>JDK7里面g是有所发展Q听说是会自动实现这一点,也就是说Q?/span>sun可能为我们做了这个工作,以后的程序中可能不需要手动释攄似数据库资源的代码了?/span>
如果的确如此Q那是不是意味着finalize()没用了呢?错。不q?/span>finalize()实用到的时候不会很多,它主要用于一些本地方法调用过E中产生的资源清理。比如你通过Native method调用c语言?/span>mellocҎ分配了一些内存空_而这部分内存是需?/span>c语言?/span>free()来进行释攄Q如果不q样Q就会生内存泄漏,所以你需要在finalize()中用Native methodҎ调用free()其释放?/span>
不过话说回来Q?/span>finalize()Ҏq不十分保险Q因?/span>finalize()只有在垃圑֛收器工作的时候才会被调用Q也是_通过它进行资源释攑ƈ不能保马上被释放,甚至可能Ҏ不会被释放(因ؓ垃圾回收器可能不会工作)Q因此,资源释放量另想办法Q别太相?/span>finalize()和垃圑֛收器了?/span>