当前位置: 代码网 > it编程>编程语言>Java > Java序列化之serialVersionUID的用法解读

Java序列化之serialVersionUID的用法解读

2025年11月21日 Java 我要评论
java序列化之serialversionuid今天讲一讲java对象中的serialversionuid,先从序列化讲起。什么是序列化序列化,简单的说,就是将一个对象转化(编码)成可以传输的输出流(

java序列化之serialversionuid

今天讲一讲java对象中的serialversionuid,先从序列化讲起。

什么是序列化

序列化,简单的说,就是将一个对象转化(编码)成可以传输的输出流(字节流)。而反序列化就是序列化的逆过程,将输入流转化(构建)成一个对象。

为什么要序列化

字节流可以用于网络传输和存储在磁盘,而对象需要转化成字节流才能在网络中传输和在磁盘上存储。

网络传输就好比打电话,声音是无法直接从电话的一端传到另一端,因此需要将声音转成电信号进行传播。

另一方面,java对象是保存在jvm的堆内存中的,也就是说,如果jvm堆不存在了,那么对象也就跟着消失了,而序列化提供了可以把对象保存下来的方案。

serialversionuid是个啥

说到序列化,serialversionuid是个不得不谈的话题。

serialversionuid 是 java 为每个序列化类(实现java.io.serializable接口的类)产生的版本标识, 可用来保证在反序列时,发送方发送的和接受方接收的是可兼容的对象。

如果接收方接收的类的 serialversionuid 与发送方发送的 serialversionuid 不一致,进行反序列时会抛出 invalidclassexception。

怎么生成serialversionuid

下载generateserialversionuid插件,就可以自动生产这个序列类的serialversionuid了。

serialversionuid是一成不变的吗

达咩! 

serialversionuid 是 java 为每个序列化类产生的版本标识!!

java序列化机制会根据编译的class自动生成一个serialversionuid作序列化版本比较用。

如果class文件的类名、方法名称发生改变,serialversionuid就会改变。

如果class文件没有发生变化(增加空格,换行,增加注释等等),就算再编译多次,serialversionuid也不会变化的。

import java.io.serializable;

public class person implements serializable {
    // 原本的serialversionuid
    private static final long serialversionuid = 904xxxxxxxxxx662l;

    private int age;
    private string name;
    private string address;

    public person(int age, string name, string address) {
        this.age = age;
        this.name = name;
        this.address = address;
    }

    public int getage() {
        return age;
    }

    public void setage(int age) {
        this.age = age;
    }

    public string getname() {
        return name;
    }

    public void setname(string name) {
        this.name = name;
    }

    public string getaddress() {
        return address;
    }
    public void setaddress(string address) {
        this.address = address;
    }
}

import java.io.serializable;

public class person implements serializable {
    // 加上tosting函数的serialversionuid
    private static final long serialversionuid = 841xxxxxxxxxxxxx884l;

    private int age;
    private string name;
    private string address;

    public person(int age, string name, string address) {
        this.age = age;
        this.name = name;
        this.address = address;
    }

    public int getage() {
        return age;
    }

    public void setage(int age) {
        this.age = age;
    }

    public string getname() {
        return name;
    }

    public void setname(string name) {
        this.name = name;
    }

    public string getaddress() {
        return address;
    }

    public void setaddress(string address) {
        this.address = address;
    }

    @override
    public string tostring() {
        return "person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

如果我手动改了serialversionuid=11111111l会怎样?如果接收方接收的类的 serialversionuid 与发送方发送的 serialversionuid 不一致,进行反序列时会抛出 invalidclassexception。

exception in thread "main" java.io.invalidclassexception: serializablestudy.person; local class incompatible: stream classdesc serialversionuid = 841xxxxxxxxxxxxx884, local class serialversionuid = 11111111

序列化和反序列化

序列化要把对象写入输出流中,反序列化就是将输出流重新构建对象,二者为逆过程。当serialversionuid改变时,一定要重新序列化,再进行反序列化。

话不多说,放代码。

以下是基于上面序列化类person,做序列化和反序列化的演示:

public class serialtest {

    public static void main(string[] args) throws ioexception {
//        序列化
        person p = new person(0,"aaa","bbbbb");
//        指定文件生成输出流
        fileoutputstream fos = new fileoutputstream("person.txt");
//        将对象写出到指定的输出流
        objectoutputstream oos = new objectoutputstream(fos);
//        将指定的对象写入objectoutputstream。
        oos.writeobject(p);
//        刷新流
        oos.flush();
        oos.close();
    }
}
public class deserialtest {
    public static void main(string[] args) throws ioexception, classnotfoundexception {
//        反序列化
//        根据指定文件生产输入流
        fileinputstream fis = new fileinputstream("person.txt");
//        从指定的输入流中读回对象消息
        objectinputstream ois = new objectinputstream(fis);
//        从objectinputstream读取一个对象
        person p = (person) ois.readobject();
        ois.close();
        system.out.println(p.tostring());
    }
}

输出的结果为:

注意:

将指定对象写入objectoutputstream时,存储针对对象本身而不是针对类,没有实现序列化的类不会参与序列化和反序列化!!

举个例子,如果person中设置一个没有实现序列化的父类home:

public class home {
    private string home;

    public string gethome() {
        return home;
    }

    public void sethome(string home) {
        this.home = home;
    }
}
public class person extends home implements serializable {
	......
}

在序列化和反序列化的过程中,即使定义了person对象的home属性,由于home中没有实现序列类,因此对象的home属性不会进行序列化处理。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com