理解serialVersionUID是什么?有什么用?如何生成?_serialversionuid是不是类似class的hashcode-程序员宅基地

技术标签: java基础  

转自:https://www.cnblogs.com/xuxinstyle/p/11394358.html

如果您曾经实现过Serializable接口,则必须遇到此警告消息

The serializable class xxx does not declare a static final serialVersionUID field of type long

那么......什么是serialVersionUID?

在Java中,serialVersionUID类似于版本控制,确保序列化和反序列化的对象都使用兼容的类。
例如,如果一个对象保存在带有serialVersionUID=1L的文件(序列化)中,当我们将文件转换回一个对象(派生)时,我们必须使用相同的serialVersionUID=1L,否则抛出InvalidClassException

参考:https://mkyong.com/java-best-practices/understand-the-serialversionuid/

1. SerialVersionUID示例

上面的语句在开头有点难以理解(至少我做过),让我们开始一个例子来了解Serializable类如何使用SerialVersionUID来实现版本控制。

 

1.1 Address.java

serialVersionUID为1L的可序列化类。

import java.io.Serializable;
 
public class Address implements Serializable{
 
       private static final long serialVersionUID = 1L;
    
       String street;
       String country;
 
       public void setStreet(String street){
           this.street = street;
       }
 
       public void setCountry(String country){
           this.country = country;
       }
 
       public String getStreet(){
           return this.street;
       }
 
       public String getCountry(){
           return this.country;
       }
 
       @Override
       public String toString() {
           return new StringBuffer(" Street : ")
           .append(this.street)
           .append(" Country : ")
           .append(this.country).toString();
       }
}

 

1.2 WriteObject.java

将Address对象写入/序列化为文件的简单类 - “c:\\ address.ser”。

 

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
 
public class WriteObject{
 
    public static void main (String args[]) {
     
       Address address = new Address();
       address.setStreet("wall street");
       address.setCountry("united states");
 
       try{
 
        FileOutputStream fout = new FileOutputStream("c:\\address.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fout);   
        oos.writeObject(address);
        oos.close();
        System.out.println("Done");
 
       }catch(Exception ex){
           ex.printStackTrace();
       } 
    }
}

1.3 ReadObject.java

从文件中读取/反序列化Address对象的简单类 - “c:\\ address.ser”。

 

import java.io.FileInputStream;
import java.io.ObjectInputStream;
 
public class ReadObject{
 
   public static void main (String args[]) {
 
       Address address;
       
       try{
 
           FileInputStream fin = new FileInputStream("c:\\address.ser");
           ObjectInputStream ois = new ObjectInputStream(fin);
           address = (Address) ois.readObject();
           ois.close();
 
           System.out.println(address);
           
       }catch(Exception ex){
           ex.printStackTrace(); 
       } 
   }
}

2.测试

让我们做一些测试来演示serialVersionUID的使用。

2.1相同的serialVersionUID

相同的serialVersionUID,在反序列化过程中没有问题

javac Address.java javac WriteObject.java javac ReadObject.java java WriteObject java ReadObject Street : wall street Country : united states

复制

2.2不同的serialVersionUID

在Address.java中,将serialVersionUID更改为2L(它是1L),然后再次编译它。

javac Address.java java ReadObject java.io.InvalidClassException: Address; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2 ... at ReadObject.main(ReadObject.java:14)

 

“ InvalidClassException”会引发,因为您使用serialVersionUID“1L”编写了一个序列化类,但尝试使用更新的序列化类serialVersionUID“2L”将其检索回来。

serialVersionUID必须在序列化和反序列化过程中匹配。

什么时候应该更新你的serialVersionUID?

如果使用对可序列化类的某些不兼容的Java类型更改更新序列化类,则必须更新serialVersionUID。

有关可序列化类的兼容和不兼容Java类型更改的详细信息,请参阅Java对象序列化规范。

3.默认的serialVersionUID有什么问题?

如果没有声明serialVersionUID,JVM将使用自己的算法生成默认的SerialVersionUID,您可以在此处检查算法。

默认的serialVersionUID计算对类详细信息非常敏感,可能因不同的JVM实现而异,并且在反序列化过程中会导致意外的InvalidClassExceptions。

3.1客户端/服务器环境

- 客户端在Windows中使用SUN的JVM。

- 服务器在Linux中使用JRockit。

客户端通过套接字向服务器发送带有默认生成的serialVersionUID(例如123L)的可序列化类,服务器可以在反序列化过程中生成不同的serialVersionUID(例如124L),并引发意外的InvalidClassExceptions。

3.2文件/数据库环境

- App#1在Windows中使用SUN的JVM。

- App#2在Linux中使用JRockit。

序列化允许保存到文件或数据库中。App#1默认生成serialVersionUID(例如123L)将可序列化类存储到数据库中,而App#2可能在反序列化过程中生成不同的serialVersionUID(例如124L),并引发意外的InvalidClassExceptions。

您可以在此处查看JVM实现列表

4.如何生成serialVersionUID

您可以使用JDK“ serialver”或Eclipse IDE自动生成serialVersionUID,详见详细信息

结论

SUN强烈建议开发人员声明serialVersionUID以避免上面列出的不同JVM问题,但我建议您应该了解什么是序列化,serialVersionUID如何实现版本控制以及您的类需要使用序列化的原因。了解serialVersionUID概念优于任何推荐的盲目。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dark868/article/details/112171379

智能推荐

如何在线打开Xmind文件 — 百度脑图在线工具_xmind在线打开-程序员宅基地

文章浏览阅读4.4w次,点赞17次,收藏7次。1.问题背景:  某些时候会接收到别人发给我们的xmind(一种思维导图)的文件,但苦于我们的电脑上没有下载Xmind软件,所以我们怎么快捷的查看该文件的内容呢?2.解决方案:Step 1:  我在网络上搜索了相关的解决方法,发现一个比较快捷的,因此推荐给大家,就是我们可以直接使用百度脑图 (https://naotu.baidu.com/)来直接打开xmind类型文件。  首先我们需要登录我们的百度账号进去,然后就进入到了以下界面:Step 2:  然后我们点击新建脑图,然后再直接点击这_xmind在线打开

关于CodeBlock在调试时断点处不停的解决方法_codeblock断点不停-程序员宅基地

文章浏览阅读480次。1、project路径名必须是纯英文。空格不知道能不能有,大家还请自己试试,这也是我自己出的问题。2、这必须是个project而不是单一的一个cpp文件。其实这已经隐含在1里面了3、本身没有打开编译器的-g标志。这个比较隐蔽,但是我试了试好像没有什么影响,大家要是1,2都试了不行可以再看看这个。具体方法:在Settings->Complier and debugger->Global complier settings->Complier settings->Complier f_codeblock断点不停

C++基本语言:1.4范围for、new内存动态分配、nullptr-程序员宅基地

文章浏览阅读857次,点赞23次,收藏18次。范围for、new内存动态分配、nullptr

lightoj 1268 Unlucky Strings (矩阵快速幂+kmp DFA 好题)-程序员宅基地

文章浏览阅读1.5k次。lightoj 1268 Unlucky Strings (矩阵快速幂+kmp DFA 好题)_unlucky string

js匿名函数使用&传参_js return anonymous()-程序员宅基地

文章浏览阅读425次。function () { alert("error");} //报错:匿名函数不能直接调用使用0x01(function () { alert("Success");})()//直接使用0x02var anonymous=function () { alert("success");}anonymous();//赋值调用传参0x01(function (m,n) { return m+n;})(10,20)//直接使用0x02var ano_js return anonymous()

微信小程序---日期时间选择器(自定义精确到分秒或时段)_小程序时间选择器颗粒度为分钟-程序员宅基地

文章浏览阅读897次。声明bug:由于此篇博客是在bindcolumnchange事件中做的值的改变处理,因此会出现当你选择时,没有点击确定,直接取消返回后,会发现选择框的值依然改变。造成原因:这一点就是由于在bindcolumnchange事件做的值改变处理造成。处理方法:如果需要确定后再改变值,请将bindcolumnchange事件中的处理操作放到bindchange事件中。效果图WXML..._小程序时间选择器颗粒度为分钟

随便推点

基于Hadoop HA集群部署HBase HA集群(详细版)_hadoop集群做了ha,如何在两个nn上部署hbase-程序员宅基地

文章浏览阅读4.6k次,点赞8次,收藏54次。前面的博客中链接1、前言已经给出Hadoop3.1.2和yarn的完整部署(但还不是高可用),此篇博客将给出Hadoop的高可用部署,以及HBase高可用,为之后应用数据层开发提供底层的BigTable支持。前面的文章,我们已经深入讨论的ZooKeeper这个中间件的原理以及分布式锁的实现,事实上zookeeper使用最广泛的场景是“选举”主从角色,Hadoop以及Hbase的高可用(主从架构..._hadoop集群做了ha,如何在两个nn上部署hbase

自动编码器与生成对抗网络:同源性与区别-程序员宅基地

文章浏览阅读827次,点赞15次,收藏22次。1.背景介绍自动编码器(Autoencoders)和生成对抗网络(Generative Adversarial Networks,GANs)都是深度学习领域的重要算法,它们在图像生成、数据压缩、特征学习等方面都有着广泛的应用。然而,这两种算法虽然在应用场景和表现效果上有很大的不同,但它们的核心思想和算法原理却是相通的。本文将从以下几个方面进行阐述:背景介绍核心概念与联系核心算法原理和...

CHI的Cache Stashing和DVM操作-程序员宅基地

文章浏览阅读1.5w次,点赞10次,收藏98次。介绍CHI协议中的Cache Stashing操作和DVM操作_cache stashing

vscode 插件_vscode插件体系详解-程序员宅基地

文章浏览阅读2.1k次。vscode 作为一款网红 IDE,其丰富的插件让人叹为观止,通过 vscode 提供的插件机制,我们几乎可以自定义 vscode 的所有细节。事实上很多 vscode 的核心功能也是通过插件实现的。本文我们将从以下三个方面详述 vscode 的插件机制:插件的基本结构插件执行环境插件的运行流程阅读本文后续内容,需要对 vscode 的插件开发有基本的了解。关于 vscode 的插件开发..._vscode插件体系的基本概念

DevOps 工程师成长日记系列四:打包_devops项目集成go语言编译打包部署环境-程序员宅基地

文章浏览阅读278次。原文地址:https://medium.com/@devfire/how-to-become-a-devops-engineer-in-six-months-or-less-part-4-package-47677ca2f058原文作者:Igor Kantor翻译君:CODING 戴维奥普斯前情提要在这个系列的第一篇文章中,我们详细地介绍了 DevOps 相关的文化和基础技能;在第二..._devops项目集成go语言编译打包部署环境

ubuntu18本地镜像源_UbuntuCore 18.04 修改国内镜像源(Ubuntu Ports)-程序员宅基地

文章浏览阅读600次。UbuntuCore 18.04 修改国内镜像源(Ubuntu Ports)工作中在全志 H3 ARM 架构上移植使用了 UbuntuCore 18.04 系统,其默认镜像源为国外源,更新缓慢。故修改使用国内中国科学技术大学的镜像源,具体修改方法如下:一、修改镜像源文件http://ports.ubuntu.com/ 为 http://mirrors.ustc.edu.cn/ubuntu-port..._ubuntu18 ports 国内源