自定义序列化
自定义序列化
递归序列化:当对某个对象序列化时,会自动序列化该对象的实例变量,某个实例对象引用到另一个对象,则被引用的对象也会被序列化。
在实例变量前加transient关键字修饰,可以指定该对象实例化时无需理会这个实例变量。
public class Student implements Serializable{
private String name;
private transient int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
try (FileOutputStream outputStream = new FileOutputStream("e://student");
FileInputStream inputStream = new FileInputStream("e://student");
ObjectOutputStream oos = new ObjectOutputStream(outputStream);
ObjectInputStream ois = new ObjectInputStream(inputStream);) {
Student s = new Student("aaa", 12);
oos.writeObject(s);
Student s2 = (Student) ois.readObject();
System.out.println(s2); //输出name=aaa,age=0
}
}
实现自定义序列化:
private void writeObject(java.io.ObjectOutPutStream out)throws IOException
private void readObject(java.io.ObjectInPutStream in)throws IOException,ClassNotFoundException
重写writeObject()方法,获得对序列化机制的控制,控制那些实例变量被序列化,怎样序列化,通过readObject()反序列化对象。private void writeObject(java.io.ObjectOutPutStream out)throws IOException
private void readObject(java.io.ObjectInPutStream in)throws IOException,ClassNotFoundException
public class Student implements Serializable{
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
private void writeObject(ObjectOutputStream out) throws IOException{
out.writeObject(new StringBuilder(name).reverse());
out.writeInt(age+1);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
this.name = ((StringBuilder)in.readObject()).reverse().toString();
this.age = in.readInt()-1;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
private Object writeReplace() throws ObjectStreamException{
return new Student("tom", 5);
}
在Student类中覆盖writeReplace() ,则该对象序列化的对象时该方法的返回值反序列化该对象得到的对象是:Student [name=tom, age=5]
与writeReplace方法对应的是readResolve方法
与writeReplace方法对应的是readResolve方法
readResolve会替代原来的反序列化的对象,readObject得到的对象将会被丢弃.
private Object readResolve(){
return name;
}
反序列化对象将会得到,name属性的值实现Externalizable接口的序列化:
public class Test2 implements Externalizable{
private int i;
private String str;
public Test2(int i, String str) {
this.i = i;
this.str = str;
}
public Test2() {
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
// TODO Auto-generated method stub
out.writeObject(str);
out.writeInt(i);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
// TODO Auto-generated method stub
str = (String) in.readObject();
i = in.readInt();
}
}
覆盖writeExternal readExternal
方法来自己决定需要序列化或反序列化哪些实例变量。当使用Externalizable
来反序列化对象时,会先调用带对象的无参构造器,所以必须提供public无参的构造器。
对象序列化的注意事项:
1.对象的类名,实例变量都会被序列化;方法、类变量、transient修饰的变量都不会被序列化
2.保证序列对象的实例变量都是可序列化的,要不然该类不可序列化
3.反序列化必须要有对象的class文件
4.读取对象的二进制文件时,必须按照序列化的顺序来反序列化