• Java-序列化和反序列化



     

    一、序列化和反序列化简介

    序列化:将对象以流的方式存入文本文档中,目的是为了对象可以跨平台存储和进行网络传输,
    		而我们进行跨平台存储和网络传输的方式就是IO,而IO支持的数据格式就是字节数组
    
    反序列化:将文档中的对象以流的方式读出
    
    • 1
    • 2
    • 3
    • 4

    比喻:序列化就是将一颗颗糖果放入一个盒子的容器中储存,而反序列化就是将盒子中的糖果一颗一颗的拿出来吃

    序列化和反序列化的时候会抛出NotSerializableException:没有序列化异常
    这是要求我们自定义的类如果需要使用序列化将对象存入文档就必须实现Serializable接口。
    该接口会给类添加一个标记,当我们进行序列化和反序列化的时候就会检测类上是否有这个标记
    
    • 1
    • 2
    • 3

     


     

    二、图解

    在这里插入图片描述
     


     

    三、ObjectOutputStream序列化流

    ①、在java.io包下

    ②、extends OutputStream

    ③、作用:将对象以流的方式写入到文件中保存

    ④、构造方法:ObjectOutputStream(OutputStream out)

    ⑤、参数:out为字节输出流

    ⑥、特有的成员方法:void writeObject(Object obj) 将指定的对象写入ObjectOutputStream

    ⑦、使用步骤

    1、创建ObjectOutputStream对象,构造方法中传递字节输出流
    2、使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
    3、释放资源
    
    • 1
    • 2
    • 3

    注意:手动打开序列化后的文件会发现看不懂,这是正常现象,因为我们是以字节的方式将对象进行存储的

    ⑧、代码

    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Day8-25//src//b1//a.txt"));
     oos.writeObject(new Teacher("小红",20,20000));
     oos.close();
    
    • 1
    • 2
    • 3

     


     

    四、ObjectInputStream反序列化流

    ①、在java.io包下
    ②、extends InputStream
    ③、构造方法:ObjectInputStream(InputStream in)
    ④、特有的成员方法:Object readObject() 从ObjectInputStream中读取对象
    ⑤、使用步骤

    1、创建ObjectInputStream对象,构造方法中传递字节输入流
    2、使用ObjectInputStream对象中的方法readObject读取保存在文本中的对象
    3、释放资源
    4、使用读取出来的对象(打印)
    
    • 1
    • 2
    • 3
    • 4

    ⑥、readObject方法声明抛出了ClassNotFoundException异常(class文件找不到)当不存在对象的class文件时抛出此异常
    所以:推出反序列化的前提

    前提:
    1、类必须实现Serializable
    2、必须存在类对象的class文件
    
    • 1
    • 2
    • 3

    ⑦、代码

    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Day8-25//src//b1//a.txt"));
    Object o = ois.readObject();
    ois.close();
    System.out.println(o);
    
    • 1
    • 2
    • 3
    • 4

     


     

    五、transient关键字

    又称为瞬态关键字,被transient修饰的成员变量不能被序列化(即不能被写入文档中)
     


     

    六、补充:

    1、static关键字

    static修饰的成员变量也不能够被序列化,序列化的都是对象
    
    • 1

    2、序列化不管对象的方法

    序列化只保存对象的状态,不管对象的方法,即使对象中有方法也无法被序列化流写入文档中

    具体原因参考这位博主的文章:序列化能保存对象的哪些内容

    3、子类和父类的序列化

    当一个父类实现了序列化,它的子类也自动实现序列化,不用显示进行实现了
     


     

    七、代码讲解

    1、题目

    1)将若干个Student对象,若干个Teacher对象,写出到d:/练习/a.txt中 ,如果文件不存在,需要先创建该文件
    2)将该文件中所有Student对象反序列化回来装入List, 所有的Teacher对象反序列化回来转入另外一个List
    
    • 1
    • 2

    2、分析

    1、将对象放入文档需要使用序列化的知识
    2、需要使用File类提供的方法exists()方法判断文件是否存在,如果不存在使用方法createNewFile()创建
    3、在进行反序列化时需要使用循环将文档中所有的对象拿出,判断条件需要使用文件输入流的available()方法,
       如果返回结果大于0则代表文档中还有内容可以继续读取,没有则退出
    4、接收到对象后还需要进行判断,如果是Student对象那么需要放入学生对象的List集合,如果是Teacher对象那么
       需要放入教师对象的List集合
    5、在判断对象是哪个对象时就可以将其打印输出,这里可以在各类中添加toString()方法方便打印查看
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3、代码展示

    import java.io.*;
    import java.util.ArrayList;
    
    public class TSTest {
        public static void main(String[] args) {
            Student s1 = new Student("张三", 10, 111);
            Student s2 = new Student("李四", 11, 222);
            Teacher t1 = new Teacher("小红", 20, 10000);
            Teacher t2 = new Teacher("小明", 23, 10000);
    
            File file = null;
            try {
                file = new File("E:\\JavaCode\\JavaSE\\Day8-25\\src\\a1\\a.txt");
                if (!file.exists()) {
                    file.createNewFile();
                } else {
                    // TODO 序列化
                    // todo 使用序列化将对象写入文件中
                    FileOutputStream fos = new FileOutputStream(file);
                    ObjectOutputStream oos = new ObjectOutputStream(fos);
                    // 将内容写入
                    oos.writeObject(s1);
                    oos.writeObject(s2);
                    oos.writeObject(t1);
                    oos.writeObject(t2);
    
    
                    try {
                        // TODO 反序列化
                        FileInputStream fis = new FileInputStream(file);
                        ObjectInputStream ois = new ObjectInputStream(fis);
                        ArrayList<Object> sList = new ArrayList<>();
                        ArrayList<Object> tList = new ArrayList<>();
                        Object o = null;
                        // 需要在外部创建一个Object对象,赋值为null
                        while (fis.available() > 0) {  // todo 代表文件中还有内容
                        // 读取内容,该行代码不能放置最后,不然最后输出结果会少一行数据
                            o = ois.readObject();
                            if (o instanceof Student) {
                                sList.add(o);
                                System.out.println("学生:" + o);
                            } else if (o instanceof Teacher) {
                                tList.add(o);
                                System.out.println("老师:" + o);
                            }
    
    
                        }
    
    
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
    
    
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
  • 相关阅读:
    【原创】辟谣,实测MyBatisPlus批量新增更新方法确实有效,且可单独使用无需跟随IService
    【Java 进阶篇】深入理解SQL查询语言(DQL)
    ORB-SLAM2 ---- Tracking::UpdateLastFrame函数
    安规电容总结
    Python | 24K纯新手的Python环境搭建之路!~(Anaconda + Jupyter)
    Avalonia常用小控件Menu
    微信小程序的页面滚动事件监听
    java基础巩固2
    Python中zip函数的使用方法
    git遇到的报错
  • 原文地址:https://blog.csdn.net/qq_52998673/article/details/126605727