引言

        在学习IO流时,我们会学到一个序列化流,和反序列化流,相信不少小伙伴学到这个是有些懵的,今天就带大家来了解一下java的对象序列化流与反序列化流

 


 

目录

一、什么是java的对象序列化流与反序列化流

 二、对象的序列化

三、对象的反序列化流

四、对象序列化中我们容易遇到的集合小问题


一、什么是java的对象序列化流与反序列化流

    - 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象

        Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。

        将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。

        整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。

        类 ObjectInputStream 和 ObjectOutputStream 是高层次的数据流,它们包含反序列化和序列化对象的方法。

 二、对象的序列化

         那么ObjectOutputStream类给我们提供了构造方法和对应的方法,我们只了解他的构造方法和序列化对象的方法。

构造方法

 

 

 序列化对象方法

 

        了解了它的两个方法之后,我们来进行代码演示

这里创建一个学生类,在主方法里面创建一个学生类对象,将学生类对象进行序列化

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class ObjectOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\Java\\oos2.txt"));

        Student s = new Student("张二狗",22);

        oos.writeObject(s);

        oos.close();

    }
}

        当我们写完代码之后,点击运行,会发现爆出一个异常:

java.io.NotSerializableException:

        进入帮助文档查看

         说明我们需要在我们的类实现这么一个接口,不然程序就会抛异常,

 

        那么我们接着对类进行实现这接口,

public class Student implements Serializable{

          实现该接口以后,我们的程序就不会抛出异常了,此外我们这实现接口后发现不用重写接口中的方法,打开帮助文档查看才知道原来该类没有方法,仅用于序列化的标识,也就是说,在进行对象序列化时,必须要实现该接口。

        此时我们的文件当中的内容

         可以发现我们的对象已经被写进去,但是我们看不懂怎么办?别慌,往下看看对象的反序列化流。

三、对象的反序列化流

        前面我们已经讲了反序列化就是把我们文件中的对象再读取出来进行反序列化,那么怎么操作呢,这里也使用到了ObjectInputStream类的构造方法和他的读取方法

构造方法

     

 读取方法

 代码实现

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

/*
    构造方法:
        ObjectInputStream​(InputStream in):创建从指定的InputStream读取的ObjectInputStream

    反序列化对象的方法:
        Object readObject​():从ObjectInputStream读取一个对象
 */
public class ObjectInputStreamDemo {
    public static void main(String[] args) throws IOException,ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\Java\\oos2.txt"));

        Object obj = ois.readObject();

        Student s = (Student)obj;

        System.out.println(s);
        ois.close();
    }
}

这时的输出结果

Student{name='张二狗', age=22}

就变成了我们能看得懂了。 

四、对象序列化中我们容易遇到的集合小问题

        1.当我们修改类文件的内容时,会出现一个问题,例如我们现在给学生类中添加一个equals方法。他就会抛出一个异常,

java.io.InvalidClassException: com.Student; local class incompatible: stream classdesc serialVersionUID = -3743788623620386195, local class serialVersionUID = -247282590948908173
    远程UID
        stream classdesc serialVersionUID = -3743788623620386195,
    本地UID 
        local class serialVersionUID = -247282590948908173

        这个异常在帮助文档是这样描述的

        那么很明显我的类不具备三个问题中的后两个,那么只能是第一个问题了,怎么解决呢,看帮助文档

         也就是说我们修改类文件时无意把他的那个版本号更改了,那么怎么避免被更改呢,这里就给我们指出了一个方法

private static final long serialVersionUID = -3743788623620386195L;

即在对象的类文件中加入该属性来声明,且该字段必须是static,final,long类型的

         2.如果我们不想类中某一个对象被序列化,可以在类的声明处加上一个transient

    private String name;
//    private int age;
    private transient int age;
    private static final long serialVersionUID = -3743788623620386195L;

Student{name='张二狗', age=0}

         可以看到年龄没有被序列化,这里显示是因为我重写的toString方法加上age的默认值是0;

        感谢大家的阅读,喜欢的可以关注我,后面会陆续给大家带来更多的分享,也欢迎大家在评论区友好交流。

 


本文转载:CSDN博客