【JAVA入门】Day43 - 序列化流和反序列化流

【JAVA入门】Day43 - 序列化流和反序列化流



        序列化流和反序列化流是字节流下的高级流类。

在这里插入图片描述
        序列化流的作用是:把 Java 中的对象写到本地文件中。
        反序列化流的作用是:把本地文件中的 Java 对象读入。

一、序列化流(对象操作输出流)

        把 Java 中的对象写到本地文件中。其中包含的方法如下:
在这里插入图片描述
        利用这两个方法,我们可以把 Java 中的一个对象写入本地文件。但要注意,直接将对象输出会出现 NotSerializableException 异常,这是因为 Javabean 类本身是不允许被序列化的,我们要先让 Javabean 类实现一个 Serializable 接口。这个接口是一个标记型接口,一旦实现了这个接口,就表明当前这个 Javabean 类可以被序列化。

package ObjectStream;

import java.io.Serializable;
import java.util.Objects;

public class Student implements Serializable {
    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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

package ObjectStream;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class ObjectStreamDemo1 {
    public static void main(String[] args) throws IOException {
        /*
            利用序列化流把一个对象写到本地中
         */

        //1.创建对象
        Student student = new Student("zhangsan",23);

        //2.创建序列化流对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\IdeaProjects\\HelloWord\\src\\ObjectStream\\student.txt"));

        //3.把对象输出到文件
        oos.writeObject(student);

        //4.释放资源
        oos.close();

    }
}

二、反序列化流(对象操作输入流)

        反序列化流可以把序列化到本地文件中的对象,读取到程序中来。
在这里插入图片描述
        反序列化流读入的对象类型是 Object 类,我们还要进行一次强制转换,把它转成本来的类型。

package ObjectStream;

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

public class ObjectStreamDemo2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        /*
            利用反序列化流把本地文件中的对象读取到程序中来
         */

        //1.创建反序列化流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\IdeaProjects\\HelloWord\\src\\ObjectStream\\student.txt"));

        //2.读入数据
        //Object obj = ois.readObject();
        Student student = (Student) ois.readObject();

        //3.打印对象
        //System.out.println(obj);
        System.out.println(student);

        //4.释放资源
        ois.close();
    }
}

三、序列化流和反序列化流的使用细节

3.1 序列号

        如果一个类实现了 Serializable 接口,就代表这个类是一个可序列化的,然后 Java 会根据这个类的构造方法、静态变量、静态方法、成员变量、成员方法等内容进行计算,生成一个 long 类型的序列号。此时如果把这个对象写入本地文件当中,这个序列号也是会被写入的。
        一旦我们又修改了这个类的内容(比如新增了属性),Java 又会重新计算一个序列号。此时,用反序列化流把本地文件读取进来的时候,就会报错。报错原因很简单:文件中的版本号,跟 Javabean 的版本号不匹配
        因此如果我们想要反复修改一个类,然后对它反复使用序列化流和反序列化流,就需要在 Javabean 类中提前设定好它的版本号,这样每次修改时,其序列号就不会改变了,也就可以反复序列化和反序列化了。
        序列号的格式如下:

private static final long serialVersionUID = 1L;

        注意它是一个私有静态常量,不可被方法修改,且名字必须叫“serialVersionUID”。

package ObjectStream;

import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;

public class Student implements Serializable {

    private static final long serialVersionUID = 1L;
    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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

3.2 不想序列化到本地的成员变量

        如果 Javabean 里的某些属性,你不想序列化到本地(保护隐私),那么你可以在变量前加一个关键字 transient 。

private transient String address;
package ObjectStream;

import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;

public class Student implements Serializable {

    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private transient String address;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}

四、读写多个对象

        如果有多个对象想要同时读写,应该如何操作呢?
        我们可以把多个对象放入一个ArrayList,序列化这个 list 对象。

package ObjectStream;

import java.io.*;
import java.util.ArrayList;

public class ObjectStreamDemo3 {
    public static void main(String[] args) throws IOException {
        /*
        序列化读写多个对象
     */

        //1.序列化多个对象
        Student s1= new Student("zhangsan", 23, "南京");
        Student s2= new Student("lisi",24,"北京");
        Student s3= new Student("wangwu",25,"上海");

        ArrayList<Student> list = new ArrayList<>();
        list.add(s1);
        list.add(s2);
        list.add(s3);

        //直接序列化list对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\IdeaProjects\\HelloWord\\src\\ObjectStream\\student.txt"));
        oos.writeObject(list);

        oos.close();

    }

}

        再反序列化这个 list 对象即可。

package ObjectStream;

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

public class ObjectStreamDemo4 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        /*
            反序列化多个对象
         */

        //1.创建反序列化流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\IdeaProjects\\HelloWord\\src\\ObjectStream\\student.txt"));

        //2.读取list对象
        ArrayList<Student> list = (ArrayList<Student>) ois.readObject();

        //3.打印
        for (Student student : list) {
            System.out.println(student);
        }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值