声明serialVersionUID进行Serializable接口版本控制

  本文目标:开发人员,在了解serialVersionUID作用的条件下,进行序列化相关类的定义操作,达到版本可控的程度。

1 场景

  Java中的序列化主要应用于以下3个场景:

  (1)对象状态持久化 - 将对象保存到文件或数据库中

  (2)网络传输优化 - 通过序列化减少网络传输数据量

  (3)RPC等的应用基础 - 远程过程调用需要以流的形式处理请求和响应

  本文以将对象保存到文件举例,说明serialVersionUID在序列化、反序列化中,如何起到版本控制的作用。

  首先一起来看正常情况下,Apple对象如何进行序列化,得到二进制数据存入文件;以及如何读取文件,将二进制数据反序列化得到Apple对象。

1.1 Apple类定义

  要进行序列化的对象,对应类需要实现Serializable接口,未实现该接口,无法进行序列化。

  serialVersionUID的1L,也会参与序列化,表示版本。

package maplegam.com;

import java.io.Serializable;

public class Apple implements Serializable {

    private static final long serialVersionUID = 1L;

    String name;
    String weight;

    public Apple(String name, String weight) {
        this.name = name;
        this.weight = weight;
    }

    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getWeight() {
        return this.weight;
    }
    public void setWeight(String weight) {
        this.weight = weight;
    }

}

1.2 apple对象序列化并存入文件

  使用java io库的ObjectOutputStream进行序列化处理,并将结果存入“abc.txt”文件。

package maplegam.com;

import java.io.*;

public class SerialzableTest {
    public static void main(String[] args) throws Exception {
        String writerPath = "D:\\abc.txt";
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(writerPath, true));
        oos.writeObject(new maplegam.com.Apple("aaa", "3.78"));
        oos.close();
    }
}

  abc.txt文件内容如下图所示:

序列化文件内容

1.3 读取文件反序列化得到apple对象

  使用java io库的ObjectInputStream进行反序列化处理,并将得到的apple对象内容打印出来。

package maplegam.com;

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

public class SerialzableReadTest {
    public static void main(String[] args) throws Exception {
        String writerPath = "D:\\abc.txt";
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(writerPath));
        Object oj = ois.readObject();
        Apple apple = (Apple) oj;
        System.out.println("Apple name:"+apple.getName());
        System.out.println("Apple weight:"+apple.getWeight());
        ois.close();
    }
}

  反序列化为对象后,打印内容如下:

反序列化结果

2 要点

2.1 类要实现Serializable接口

  进行序列化的类,没有实现Serializable接口时,会出现报错“java.io.NotSerializableException”。

未实现Serialable接口报错

2.2 类中的serialVersionUID版本要一致

  serialVersionUID版本如果不一致(比如序列化时客户端引用的该类版本为1L,服务端引用的该类版本为2L),会出现报错“java.io.InvalidClassException: maplegam.com.Apple; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2”。

版本不一致报错

3 总结/练习

  在需要序列化的类中,声明serialVersionUID是一个好习惯,能提高代码阅读效率。

  在代码走查阶段,如果发现客户端、服务端该值不一样,就能提前发现问题,不用等到上线报错后,从日志中看出是该问题。

  可以参照前“1 场景”、“2 要点”内容,尝试在序列化过程中,声明serialVersionUID,查看版本一致、不一致的不同处理结果。

  • 12
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值