java自定义序列化的具体使用
目录
- 1.问题引出
- 2.解决办法
- 3.另外一种自定义序列化机制(介绍Externalizable)
1.问题引出
在某些情况下,我们可能不想对于一个对象的所有field进行序列化,例如我们银行信息中的设计账户信息的field,我们不需要进行序列化,或者有些field本省就没有实现Serializable接口。
java中的序列化是递归序列化,也就是你的field的引用类型中也有field可以被序列化,那么就会在序列化当前对象的时候,一同序列化
2.解决办法
【java自定义序列化的具体使用】使用transient(瞬变现象;过往旅客;候鸟)关键字来修饰,该关键字只能修饰属性,这样在序列化的时候,这个属性就会用默认值,例如int类型用0,引用对象用null;
但是使用transient关键字修饰的field虽然简单方便,但是会被完全隔离在序列化机制之外,这样导致在反序列化回复java对象的时候,无法取得该field的值。
因此我们可以使用自定义序列化机制,可以让程序控制如何序列化各field,甚至完全不序列化某些field(这样就与transient相同),在序列化和反序列化过程中需要特殊处理的类应该提供如下特殊签名的方法,这些特殊的方法用以实现自定义的序列化
private void writeObject(java.io.ObjectOutputStream out) throws IOException; private void readObject(java.io.ObjectInputStream in)throws IOException,ClassNotFoundException; private void readObejctNoData()throws ObejctStreamException;
热爱你所写的每一行的代码
writeObject()方法负责写入特定类的实例状态,通过重写这个方法,程序员可以完全获得对序列化机制的控制,可以自主决定那些field需要序列化,需要怎么序列化,默认情况(函数体为空)该方法会调用out.defaultWriteObject来保存java对象的各field,从而达到实现序列化java对象状态的目的
readObject负责从流中读取并且回复对象的field,通过重写该方法,程序员,可以获得对反序列化机制的控制,对于反序列化各个field的顺序应该和序列化各个field的顺序相同。
至于当序列化流不完整时,readObjectNoData可以正确的初始化反序列化的对象,例如接收方接收到的序列化流残缺,或者序列化版本不同,则使用readObjectNoData来默认的初始化。
例子(对于person的改写):
class Person implements Serializable{ private String name; private int age; public Person(String name,int age) {this.name=name; this.age=age; } //自动生成的Get和Set方法 public String getName() {return name; } public void setName(String name) {this.name = name; } public int getAge() {return age; } public void setAge(int age) {this.age = age; } private void writeObject(ObjectOutputStream out) throws IOException {//将名字翻转之后写入二进制流out.writeObject(new StringBuffer(this.name).reverse()); out.writeInt(this.age); } private void readObject(ObjectInputStream in)throws IOException,ClassNotFoundException {this.name=((StringBuffer)in.readObject()).reverse().toString(); //会抛出异常,因为这里的这样写法导致同this.age=in.readInt(); }}
应该提醒的是,这个自定义的功能十分强大
另外一种替换性的改写:
//注意:这个方法由序列化机制调用,只要该方法存在就,它的访问控制符就可以为private protected package-private中的任意一种 private Object writeReplace() throws ObjectStreamException {ArrayList