继续“对象的序列化和反序列化”:
如果希望进一步控制对象的序列化和反序列化的方式,步骤如下:
- 我们可以在以上的User类中提供一个readObject()和writeObject()方法。
- 当ObjectOutputStream(对象输出流)对一个对象进行序列化时,如果该对象具有writeObject()方法,那么就执行这个方法,否则就按默认的方式序列化。
- 在writeObject()方法中,可以调用ObjectOutputStream的defaultWriteObject()方法,使得对象输出流执行默认序列化操作。
- 当ObjectInputStream(对象输入流)对一个对象进行反序列化的时候,如果该对象具有readObject()方法,那么就执行这个方法,否则就按默认的方式反序列化。
- 在readObject()方法中,可以调用ObjectInputStream的defaultReadObject()方法,使得对象的输入流执行默认的反序列化操作。
例如修改后的Java类:为User类提供了writeObject()和readObject()方法,使得被transient关键字修饰的password属性能够进行特殊的序列化。在writeObject()方法中先对name属性进行了默认的序列化,接着把password属性进行加密后再序列化,具体办法为获得password属性的字节数组,把数组中的每个字节的二进制位取反,再把取反后的字节数组写到对象输出流中。
package safe;
import java.io.*;
public class User implements Serializable {
private String name;
private transient String password;
public User(String name, String password) {
this.name=name;
this.password=password;
}
public String toString() {
return name + " " + password;
}
/** 加密数组,将buff数组中的每个字节的每一位取反
* 例如13的二进制为00001101,取反后为11110010
*/
private byte[] change(byte[] buff){
for(int i=0;i<buff.length;i++){
int b=0;
for(int j=0;j<8;j++){
int bit=(buff[i]>>j & 1)==0 ? 1:0;
b+=(1<<j)*bit;
}
buff[i]=(byte)b;
}
return buff;
}
private void writeObject(ObjectOutputStream stream)throws IOException {
stream.defaultWriteObject(); //先按默认方式序列化
stream.writeObject(change(password.getBytes()));
}
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject(); //先按默认方式反序列化
byte[] buff=(byte[])stream.readObject();
password = new String(change(buff));
}
public static void main(String[] args) throws Exception{
User user = new User("Tom", "123456");
System.out.println("Before Serialization:" + user);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
//把User对象序列化到一个字节缓存中
ObjectOutputStream o =new ObjectOutputStream(buf);
o.writeObject(user);
//从字节缓存中反序列化User对象
ObjectInputStream in =new ObjectInputStream(
new ByteArrayInputStream(buf.toByteArray()));
user= (User)in.readObject();
System.out.println("After Serialization:" + user);
}
}
在User对象序列化的数据中,保存了password属性的加密数据,在反序列化过程中,会把password的加密数据再恢复到password属性。以上程序的打印结果为:
Before Serialization:weidong tomcat After Serialization:weidong tomcat