1.序列化的类要继承Serializable接口。其父类也需要实现这个接口。否则反序列化抛异常。
2.序列化类A,引用了另外一个类B的实例,那么类B也需要实现接口。如果两个A的实例,引用了同一个B实例,那么B只序列化一次。
3.A实例序列化后,反序列化的A的实例,与原实例是两个对象。这点要注意,反序列化过程不调用构造函数,因此单例模式时,会出问题。这时需要重写readResolve方法。一般此方法为private方法,因为如果父类有此方法,子类没有重写,那么子类反序列化将得到父类对象实例。
4.可以设置序列化的过滤器。反序列化时,会自动调用过滤器的inputcheck方法。
5.可以自定义序列化。有两种方法
一种是在序列化类中写writeObject和readObject方法。这种方法,反序列化时不会调用构造函数。前者控制序列化时的操作,后者是前者的反操作。也可以写writeReplace方法。这个方法可以将对象转换成其他对象。反序列化时会先调用writeObject,如果该方法返回的另外一个对象也有这个方法则继续调用,直到没有,然后再调用readObject方法。
另一种方法,实现Externailzable接口。这个接口强制实现自定义序列化。性能较第一种略好。这个接口有两个方法
void readExternal,和writeExternal方法。除了函数签名与第一种不一样,其他用法一样。这个方法的反序列化会调用无参构造函数。因此一定要有无参的构造函数。
第二种方法因为强制实现自定义序列,编程略麻烦,因此一般使用第一种方法序列化。
6.对象的类名,实例变量,都会被序列化,方法,类变量,transient实例变量(瞬态变量)都不会被实例化。如果想让某个实例变量不要序列化,应该加上transient修饰符。不应该加staic。
7.序列化还有一个serialVersionUID指定class文件的版本号。如果版本号没变,但是class变量变了。仍然可以反序列化。(如果修改了实例变量,那么则应该修改这个版本号)
package objStream;
import java.io.FileInputStream;
import java.io.ObjectInputFilter;
import java.io.ObjectInputStream;
public class FilterTest {
public static void main(String[] args) {
try(
var oid=new ObjectInputStream(new FileInputStream("out1.txt"));
){
//为序列化设置过滤器。当反序列化时,过滤器的checkInput方法会被自动激发。
//1、用lambda表达式,因为ObjectInputFilter是一个函数式接口。需要实现checkInput方法。这个方法有一个info参数。所以info->{}。
oid.setObjectInputFilter(filterInfo -> {
//2、重写checkinput方法,首先要遵循他默认的checkinput结果。因此要先得到一个ObjectInputFilter对象。
var serialFilter=ObjectInputFilter.Config.getSerialFilter();
if(serialFilter!=null) {
//3、利用已有的过滤器,得到默认的status结果。如果结果不是undecide,就返回结果。
var status = serialFilter.checkInput(filterInfo);
if (status != ObjectInputFilter.Status.UNDECIDED) {
return status;
}
}
//4、如果是undecided,继续判断。此处为拓展原来的。
if(filterInfo.references()!=1) {
return ObjectInputFilter.Status.REJECTED;
}
if(filterInfo.serialClass()!=null&&filterInfo.serialClass()!=Person.class){
return ObjectInputFilter.Status.REJECTED;
}
//5、如果都不是以上情况,继续返回不确定。
return ObjectInputFilter.Status.UNDECIDED;
});
}catch (Exception ex){
ex.printStackTrace();
}
}
}
上面代码时设置序列化过滤器。
package objStream;
import java.io.*;
public class sameTest {
public static void main(String[] args) {
Teacher teacher=new Teacher("张三");
var stu1=new Student("李四",teacher);
var stu2=new Student("王五",teacher);
try {
var oos=new ObjectOutputStream(new FileOutputStream("same.txt"));
var ois=new ObjectInputStream(new FileInputStream("same.txt"));
oos.writeObject(teacher);
oos.writeObject(stu1);
oos.writeObject(stu2);
var teacher1=(Teacher) ois.readObject();
var stu11=(Student)ois.readObject();
var stu22=(Student)ois.readObject();
System.out.println(teacher1);
System.out.println(teacher);
System.out.println(stu1);
System.out.println(stu2);
System.out.println(stu11);
System.out.println(stu22);
System.out.println("stu1,stu11----"+ stu1.equals(stu11));
System.out.println("stu2,stu22----"+ stu2.equals(stu22));
System.out.println("stu1.teac,teac----"+ stu1.getTeacher().equals(teacher));//true
System.out.println("stu1.teac,stu11.teac----"+ stu1.getTeacher().equals(stu11.getTeacher()));//false
System.out.println("stu1.teac,stu2.teac----"+ stu1.getTeacher().equals(stu2.getTeacher()));//true
System.out.println("stu11.teac,stu22.teac----" +stu11.getTeacher().equals(stu22.getTeacher()));//true
System.out.println("teac,teac1----" +teacher.equals(teacher1));
//得出结论,反序列化后的对象和原对象不是一个对象。
//对于引用同一个对象的实例的两个不同对象,引用的同一个实例只序列化一次,所以这个实例是同一个。
//反序列化时,不经过构造器,因此如果是单例或者是枚举类,则需要重写readResolve方法,以保证反序列化以后,还是原来的实例。否则将会生成新的实例
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Teacher implements Serializable{
public Teacher(String name){
this.name=name;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Teacher{" +
"name=‘" + name + ‘\‘‘ +
‘}‘;
}
}
class Student implements Serializable{
public Student(String name,Teacher teacher){
this.name=name;
this.teacher=teacher;
}
private String name;
private Teacher teacher;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student{" +
"name=‘" + name + ‘\‘‘ +
", teacher=" + teacher +
‘}‘;
}
}
上面代码运行结果是

原文:https://www.cnblogs.com/tomato190/p/12633209.html