自定义 writeObject 方法和 readObject 方法
如果在实现Serializable接口的类中自定义 writeObject 方法和 readObject 方法,则不会调用默认的方法:
package serializable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = 140932343675039705L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString(){
return "学生:" + name;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
System.out.println("readObject exec...");
}
private void writeObject(ObjectOutputStream out) throws IOException{
System.out.println("writeObject exec...");
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
Student student = new Student();
student.setName("小明");
String filePath = "/Users/dcc/Downloads/student";
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filePath));
out.writeObject(student);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));
Student student1 = (Student) in.readObject();
System.out.println(student1);
}
}
程序输出结果:
writeObject exec...
readObject exec...
学生:null
因为在 writeObject 方法中只打印了日志,没有序列化 name 字段,所以 readObject 方法没有反序列化出 name.可以在自定义的writeObject 方法和 readObject 方法中调用默认方法:
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
System.out.println("readObject exec...");
}
private void writeObject(ObjectOutputStream out) throws IOException{
out.defaultWriteObject();
System.out.println("writeObject exec...");
}
修改之后 name 字段序列化和反序列化均成功,程序输出:
writeObject exec...
readObject exec...
学生:小明
writeReplace 方法和 readResolve 方法
writeReplace 方法可以替换序列化的对象;readResolve 方法是替换反序列化的对象:
看如下代码:
package serializable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = 140932343675039705L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString(){
return "学生:" + name;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
System.out.println("readObject exec...");
}
private void writeObject(ObjectOutputStream out) throws IOException{
out.defaultWriteObject();
System.out.println("writeObject exec...");
}
private Object writeReplace() throws ObjectStreamException{
System.out.println("writeReplace exec...");
return this;
}
private Object readResolve() throws ObjectStreamException{
System.out.println("readResolve exec...");
return this;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
Student student = new Student();
student.setName("小明");
String filePath = "/Users/dcc/Downloads/student";
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filePath));
out.writeObject(student);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));
Student teacher = (Student) in.readObject();
System.out.println(teacher);
}
}
程序运行结果:
writeReplace exec...
writeObject exec...
readObject exec...
readResolve exec...
学生:小明
可以看出:writeReplace 方法是在 writeObject 方法之前执行;readResolve 方法是在 readResolve 方法之后执行。
修改上面的代码:
package serializable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Teacher implements Serializable {
private static final long serialVersionUID = 4644753740588166024L;
private String teacherNo;
public Teacher(String teacherNo) {
this.teacherNo = teacherNo;
}
@Override
public String toString() {
return "老师:" + teacherNo;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
System.out.println("Teacher readObject exec...");
}
private void writeObject(ObjectOutputStream out) throws IOException{
out.defaultWriteObject();
System.out.println("Teacher writeObject exec...");
}
}
public class Student implements Serializable {
private static final long serialVersionUID = 140932343675039705L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString(){
return "学生:" + name;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
System.out.println("readObject exec...");
}
private void writeObject(ObjectOutputStream out) throws IOException{
out.defaultWriteObject();
System.out.println("writeObject exec...");
}
private Object writeReplace() throws ObjectStreamException{
System.out.println("writeReplace exec...");
return new Teacher("007");
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
Student student = new Student();
student.setName("小明");
String filePath = "/Users/dcc/Downloads/student";
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filePath));
out.writeObject(student);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));
Student student1 = (Student) in.readObject();
System.out.println(student1);
}
}
程序输出:
writeReplace exec...
Teacher writeObject exec...
Teacher readObject exec...
Exception in thread "main" java.lang.ClassCastException: serializable.Teacher cannot be cast to serializable.Student
at serializable.Student.main(Student.java:57)
可以看到序列化的小明同学Student对象已经被writeReplace方法替换成了Teacher对象,而且执行的是Teacher类中定义的 writeObject 方法和 readObject 方法。
反序列化处代码修改:
ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));
Teacher teacher = (Teacher) in.readObject();
System.out.println(teacher);
程序输出结果:
writeReplace exec...
Teacher writeObject exec...
Teacher readObject exec...
老师:007
我们在Student 类中增加 readResolve 方法:
private Object readResolve() throws ObjectStreamException{
System.out.println("readResolve exec...");
return new Teacher("001");
}
此时反序列化得到的老师对象仍是“老师:007”而不是“老师:001”,因为反序列化出的是Teacher对象,不会调用Student的readResolve 方法。
我们接着在Teacher类中添加 readResolve 方法:
private Object readResolve() throws ObjectStreamException{
System.out.println("Teacher readResolve exec...");
return new Teacher("001");
}
此时序列化得到的老师对象才是“老师:001”。
我们把Student和Teacher类中的writeObject 方法、 readObject 方法、writeReplace 方法和、readResolve 方法四种方法都补齐,看一下调用顺序:
package serializable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
public class Teacher implements Serializable {
private static final long serialVersionUID = 4644753740588166024L;
private String teacherNo;
public Teacher(String teacherNo) {
this.teacherNo = teacherNo;
}
@Override
public String toString() {
return "老师:" + teacherNo;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
System.out.println("Teacher readObject exec...");
}
private void writeObject(ObjectOutputStream out) throws IOException{
out.defaultWriteObject();
System.out.println("Teacher writeObject exec...");
}
private Object writeReplace() throws ObjectStreamException {
System.out.println("Teacher writeReplace exec...");
return this;
}
private Object readResolve() throws ObjectStreamException{
System.out.println("Teacher readResolve exec...");
return new Teacher("001");
}
}
package serializable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = 140932343675039705L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString(){
return "学生:" + name;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
System.out.println("readObject exec...");
}
private void writeObject(ObjectOutputStream out) throws IOException{
out.defaultWriteObject();
System.out.println("writeObject exec...");
}
private Object writeReplace() throws ObjectStreamException{
System.out.println("writeReplace exec...");
return new Teacher("007");
}
private Object readResolve() throws ObjectStreamException{
System.out.println("readResolve exec...");
return new Teacher("001");
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
Student student = new Student();
student.setName("小明");
String filePath = "/Users/dcc/Downloads/student";
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filePath));
out.writeObject(student);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));
Teacher teacher = (Teacher) in.readObject();
System.out.println(teacher);
}
}
程序输出结果:
writeReplace exec...
Teacher writeReplace exec...
Teacher writeObject exec...
Teacher readObject exec...
Teacher readResolve exec...
老师:001