Serializable与serialVersionUID的作用

总述

下面我通过三种场景来表现出Serializable与serialVersionUID的作用。

  1. 没有实现序列化接口Serializable的场景
  2. 实现了序列化接口Serializable,但没指定serialVersionUID值的场景
  3. 实现了序列化接口Serializable,并指定serialVersionUID值的场景

一、未实现序列化接口场景

实体类Student没有实现Serializable接口

1.实体类
import java.io.Serializable;

/**
 * @author: kqyin
 * @date: 2021/11/23 17:04
 * @Description: 学生
 */
public class Student /*implements Serializable*/ {
    //private static final long serialVersionUID = -1001598034465383803L;
    // id
    private String id;

    // 姓名
    private String userName;

    // 性别
    private boolean sex;

    // 手机号
    // private String phone;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public boolean isSex() {
        return sex;
    }

    public void setSex(boolean sex) {
        this.sex = sex;
    }

/*    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }*/

    @Override
    public String toString() {
        return "Student{" +
                "id='" + id + '\'' +
                ", userName='" + userName + '\'' +
                ", sex=" + sex +
                '}';
    }
}
2.测试类
import java.io.*;

/**
 * @author: kqyin
 * @date: 2021/11/23 17:04
 * @Description: 序列化测试
 */
public class SerialVersionUIDTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        writeObject();
        readObject();
    }

    /**
     * @Author kqyin
     * @Date 2021/11/23 17:22
     * @Description 将object序列化写到文件中
     */
    private static void writeObject() throws IOException {
        Student student = new Student();
        student.setId("100000");
        student.setUserName("张三");
        student.setSex(true);
        FileOutputStream fileOutputStream = new FileOutputStream("D:\\a.txt");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(student);
    }

    /**
     * @Author kqyin
     * @Date 2021/11/23 17:23
     * @Description 将文件中的对象读取成对象
     */
    private static void readObject() throws IOException, ClassNotFoundException {
        FileInputStream fileInputStream = new FileInputStream("D:\\a.txt");
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        Student student1 = (Student) objectInputStream.readObject();
        System.out.println(student1.toString());
    }
}
3.序列化报错

由于实体类Student未实现Serializable接口,因此在将对象序列化时,报错

Exception in thread "main" java.io.InvalidClassException: Student; class invalid for deserialization
	at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:169)
	at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:885)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2099)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1624)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:464)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)
	at SerialVersionUIDTest.readObject(SerialVersionUIDTest.java:40)
	at SerialVersionUIDTest.main(SerialVersionUIDTest.java:13)

二、实现序列化接口,不给定serialVersionUID场景

1.实体类

实体类Student实现Serializable接口,但未给定serialVersionUID值。

import java.io.Serializable;

/**
 * @author: kqyin
 * @date: 2021/11/23 17:04
 * @Description: 学生
 */
public class Student implements Serializable {
    //private static final long serialVersionUID = -1001598034465383803L;
    // id
    private String id;

    // 姓名
    private String userName;

    // 性别
    private boolean sex;

    // 手机号
    // private String phone;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public boolean isSex() {
        return sex;
    }

    public void setSex(boolean sex) {
        this.sex = sex;
    }

/*    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }*/

    @Override
    public String toString() {
        return "Student{" +
                "id='" + id + '\'' +
                ", userName='" + userName + '\'' +
                ", sex=" + sex +
                '}';
    }
}
2.正常序列化和反序列化

执行测试方法,可以正常序列化和反序列化
在这里插入图片描述

3.给实体类增加字段

给实体类Student增加字段phone

import java.io.Serializable;

/**
 * @author: kqyin
 * @date: 2021/11/23 17:04
 * @Description: 学生
 */
public class Student implements Serializable {
    //private static final long serialVersionUID = -1001598034465383803L;
    // id
    private String id;

    // 姓名
    private String userName;

    // 性别
    private boolean sex;

    // 手机号
    private String phone;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public boolean isSex() {
        return sex;
    }

    public void setSex(boolean sex) {
        this.sex = sex;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id='" + id + '\'' +
                ", userName='" + userName + '\'' +
                ", sex=" + sex +
                '}';
    }
}
4.反序列化报错

只执行测试类中readObject方法,进行反序列化,提示serialVersionUID值不同。这是因为没有指定serialVersionUID,serialVersionUID由于实体类的结构变动,计算的serialVersionUID值不同,导致反序列化失败。

Exception in thread "main" java.io.InvalidClassException: Student; local class incompatible: stream classdesc serialVersionUID = -1001598034465383803, local class serialVersionUID = -254405469545206643
	at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1941)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1807)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2098)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1624)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:464)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)
	at SerialVersionUIDTest.readObject(SerialVersionUIDTest.java:37)
	at SerialVersionUIDTest.main(SerialVersionUIDTest.java:11)

三、实现序列化接口,并给定serialVersionUID场景

1.实体类

实体类实现Serializable接口,并指定serialVersionUID的值,此时没有phone字段。

import java.io.Serializable;

/**
 * @author: kqyin
 * @date: 2021/11/23 17:04
 * @Description: 学生
 */
public class Student implements Serializable {
    private static final long serialVersionUID = -1001598034465383803L;
    // id
    private String id;

    // 姓名
    private String userName;

    // 性别
    private boolean sex;

    // 手机号
    //private String phone;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public boolean isSex() {
        return sex;
    }

    public void setSex(boolean sex) {
        this.sex = sex;
    }

/*    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }*/

    @Override
    public String toString() {
        return "Student{" +
                "id='" + id + '\'' +
                ", userName='" + userName + '\'' +
                ", sex=" + sex +
                '}';
    }
}
2.只进行序列化

只执行测试类writeObject()方法,进行序列化。

3.给实体增加字段

给实体类Student增加phone字段,改变toString方法,使得结果更清晰,也可以不改变。

import java.io.Serializable;

/**
 1. @author: kqyin
 2. @date: 2021/11/23 17:04
 3. @Description: 学生
 */
public class Student implements Serializable {
    private static final long serialVersionUID = -1001598034465383803L;
    // id
    private String id;

    // 姓名
    private String userName;

    // 性别
    private boolean sex;

    // 手机号
    private String phone;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public boolean isSex() {
        return sex;
    }

    public void setSex(boolean sex) {
        this.sex = sex;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id='" + id + '\'' +
                ", userName='" + userName + '\'' +
                ", sex=" + sex +
                ", phone='" + phone + '\'' +
                '}';
    }
}
4.反序列化成功

可以看到即使增加phone字段,并且修改了类里的方法,依旧反序列化成功。
在这里插入图片描述

总结

通过上述三个场景的试验,可以得知

  1. 实现Serializable接口,标注该实体类可以被序列化
  2. serialVersionUID指定唯一值,使结构变动的类依旧可以反序列化成功
  3. 如果serialVersionUID值发生变动,会导致反序列化失败
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值