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 +
- '}';
- }
- }
上面代码运行结果是
来源: http://www.bubuko.com/infodetail-3491806.html