IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java序列化与反序列化 -> 正文阅读

[Java知识库]Java序列化与反序列化

序列化与反序列化

什么是序列化和反序列化

Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复为Java对象的过程。通过徐序列化和反序列化实现网络传输、本地存储的目的。

1.Serializable实现Java序列化

要实现Java对象的序列化,只要将类实现标识接口——Serializable接口即可,不需要我们重写任何方法就可以实现序列化。

案例:Java实现Serializable接口进行序列化案例。

编写实体类

import java.io.Serializable;
import java.util.List;

public class Student implements Serializable {
    /**
     * 学号
     */
    private String stuNum;
    /**
     * 姓名
     */
    private String stuName;
    /**
     * 教师姓名:一个学生可以有多个老师
     */
    private List<String> teacherList;
    //无参数构造方法
    public Student() {
    }
    //全参构造方法
    public Student(String stuNum, String stuName, List<String> teacherList) {
        this.stuNum = stuNum;
        this.stuName = stuName;
        this.teacherList = teacherList;
    }
    @Override
    public String toString() {
        return "Student{" +
                "stuNum='" + stuNum + '\'' +
        ", stuName='" + stuName + '\'' +
                ", teacherList=" + teacherList +
                '}';
    }
    public String getStuNum() {
        return stuNum;
    }
    public void setStuNum(String stuNum) {
        this.stuNum = stuNum;
    }
    public String getStuName() {
        return stuName;
    }
    public void setStuName(String stuName) {
        this.stuName = stuName;
    }
    public List<String> getTeacherList() {
        return teacherList;
    }
    public void setTeacherList(List<String> teacherList) {
        this.teacherList = teacherList;
    }
}

编写Java对象序列化和反序列化工具类

import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.InputStream;

public class MySerializeUtil {
    /**
     * 将对象序列化到指定文件中
     * @param obj
     * @param fileName
     */
    public static void mySerialize(Object obj,String fileName) throws
            IOException {
        OutputStream out=new FileOutputStream(fileName);
        ObjectOutputStream objOut=new ObjectOutputStream(out);
        objOut.writeObject(obj);
        objOut.close();
    }
    /**
     * 从指定文件中反序列化对象
     * @param fileName
     * @return
    1.1.3 测试对象的序列化和反序列化
    运行结果:
     */
    public static Object myDeserialize(String fileName) throws IOException,
            ClassNotFoundException {
        InputStream in=new FileInputStream(fileName);
        ObjectInputStream objIn=new ObjectInputStream(in);
        Object obj=objIn.readObject();
        return obj;
    }
}

测试对象的序列化和反序列化

public class MainTest {
    public static void main(String[] args) {
        List<String> teacherList=new ArrayList<>();
        teacherList.add("空空道人");
        teacherList.add("贾代儒");
        Student stu1=new Student("1001", "贾宝玉", teacherList);
        System.out.println("原始对象:"+stu1);
        String fileName="stu01.txt";
        try {
//对象序列化
            MySerializeUtil.mySerialize(stu1, fileName);
            System.out.println("序列化原始对象完成!OK!");
//对象的反序列化
            Object obj=MySerializeUtil.myDeserialize(fileName);
            if(obj instanceof Student){
                Student stuNew= (Student) obj;
                System.out.println("反序列化之后的对象:"+stuNew);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果

在这里插入图片描述

部分属性的序列化

实现部分字段序列化的方式:
使用transient修饰符
使用static修饰符
默认方法writeObject和readObject。

使用transient修饰符

修改实体类,将实体类中不想序列化的属性添加transient修饰词。

public class Student implements Externalizable {
private String stuNum;
private transient String stuName;
private transient List<String> teacherList;
......

重新运行测试类的结果:
我们将实体类中的stuName和teacherList属性添加了transient修饰词,因此对象被序列化的时候忽略这两个属性。通过运行结果可以看出。
在这里插入图片描述

使用static修饰符

static修饰符修饰的属性也不会参与序列化和反序列化。
修改实体类,将实体类中不想序列化的属性添加static修饰词。

public class Student implements Externalizable {
private String stuNum;
private static String stuName;
private List<String> teacherList;
......

修改测试类,在完成原始对象的序列化之后再对static修饰的变量进行一次赋值操作:
在这里插入图片描述
重新运行测试类的结果:
我们将实体类中的stuName属性添加了transient修饰词,因此对象被序列化的时候忽略这个属性。通过运行结果可以看出。
在这里插入图片描述

默认方法writeObject和readObject

修改实体类,将transient修饰词去掉,添加两个方法。

public class Student implements Serializable {
    private String stuNum;
    private String stuName;
    private List<String> teacherList;
    private void writeObject(ObjectOutputStream objOut) throws IOException {
        System.out.println("writeObject-----------");
        objOut.writeObject(stuNum);
        objOut.writeObject(stuName);
    }
    private void readObject(ObjectInputStream objIn) throws IOException,
            ClassNotFoundException {
        System.out.println("readObject-----------");
        stuNum= (String) objIn.readObject();
        stuName= (String) objIn.readObject();
    }
    ......

重新运行测试类的结果:
我们在添加的方法中只对stuNum和stuName属性做了序列化和反序列化的操作,因此只有这个两个属性可以被序列化和反序列化。
在这里插入图片描述

2.Externalizable实现Java序列化

刚刚我们说实现部分属性序列化的方式有多种,最后一种来啦!就是通过实现Eexternalizable接口。Externalizable继承自Serializable,使Externalizable接口需要实现readExternal方法和writeExternal方法来实现序列化和反序列化。

代码实现:

public class Student implements Externalizable {
    /**
     * 学号
     */
    private String stuNum;
    /**
     * 姓名
     */
    private String stuName;
    /**
     * 教师姓名:一个学生可以有多个老师
     */
    private List<String> teacherList;
    //无参数构造方法
    public Student() {
    }
    //全参构造方法
    public Student(String stuNum, String stuName, List<String> teacherList) {
        this.stuNum = stuNum;
        this.stuName = stuName;
        this.teacherList = teacherList;
    }
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(stuNum);
        out.writeObject(stuName);
//out.writeObject(teacherList);
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException,
            ClassNotFoundException {
        stuNum= (String) in.readObject();
        stuName= (String) in.readObject();
//teacherList= (List<String>) in.readObject();
    }
    @Override
    public String toString() {
        return "Student{" +
                "stuNum='" + stuNum + '\'' +
                ", stuName='" + stuName + '\'' +
                ", teacherList=" + teacherList +
                '}';
    }
    public String getStuNum() {
        return stuNum;
    }
    public void setStuNum(String stuNum) {
        this.stuNum = stuNum;
    }
    public String getStuName() {
        return stuName;
    }
    public void setStuName(String stuName) {
        this.stuName = stuName;
    }
    public List<String> getTeacherList() {
        return teacherList;
    }
    public void setTeacherList(List<String> teacherList) {
        this.teacherList = teacherList;
    }
}

测试结果:
在这里插入图片描述
Externalizable接口继承了Serializable接口,所以实现Externalizable接口也能实现序列化和反序列化。
Externalizable接口中定义了writeExternal和readExternal两个抽象方法,这两个方法其实对应Serializable接口的writeObject和readObject方法。可以这样理解:Externalizable接口被设计出来的目的就是为了抽象出writeObject和readObject这两个方法,但是目前这个接口使用的并不多。

3.Serializable VS Externalizable

在这里插入图片描述

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 16:29:19  更:2021-07-31 16:30:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 1:27:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码