为什么java中序列化的serialVersionUID总是无意义的?

简介: 这个题目不主要讲serialVersionUID作用,而是讲后面的那一串数字的意义,当然也会对java的这个serialVersionUID的作用进行一个讲解。这篇文章是我积压了很久的一篇文章,写了一半,几个月了才发现,于是拿出来好好整理一下。

一、serialVersionUID的作用


通过java进行网络之间的数据传输是不能直接把对象进行传的,需要在发送端把数据切分,在接收端对切分的数据进行重装。这种切分和重装的方式就叫做序列化。下面我们举一个例子:


(1)不指定serialVersionUID


首先我们定义一个User类,继承Serializable接口

v2-beeb617cf179e12bf6cd0dc010b1fa71_1440w.jpg

然后序列化

v2-eee891eab322f2f838c139bfdbc1da9d_1440w.jpg

反序列化

v2-07ab3a07b994517ac46401c66904c6ba_1440w.jpg

现在我们举了一个序列化的例子,没有指定serialVersionUID,此时程序在编译的时候就会自动为我们生成一个ID号,整个过程是这样的:


(1)发送端不指定serialVersionUID,编译器为我们默认生成,并序列化保存在流中发送到接收端。(2)接收端把serialVersionUID保存起来,进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化。也就是说传过来的ID和本地ID不一致时候就会出现错误。


现在验证一下第二种情况:

v2-20d6b39749c5d14a15940a712c038bae_1440w.jpg

我们再去反序列化的时候,因为JVM会把传来的字节流中的serialVersionUID与本地相应实体的serialVersionUID进行比较,发现不一致,因此会出现异常错误:

v2-655f8c5f661ee2a9617ec90ee70b9089_1440w.jpg

(2)指定serialVersionUID


这个情况就不展示了,不断你之前添加了多少个字段,或者进行更改,因为serialVersionUID唯一,因此反序列化都不会出现错误。

OK,这就是java中这个serialVersionUID的作用,其实就是给这个类添加一个身份ID,进行在序列化之前和之后进行版本的比对。 上面这个其实也是一个面试常问的一个问题,再次凑巧给总结了一下,不过今天的主题不是讲这个serialVersionUID的,而是后面的那一串数字为什么总是无意义的?


二、为什么总是无意义的ID?


java序列化中的serialVersionUID后面我们通常是1L、或者是xxxL。这些数字有什么意义呢?为什么我们总是需要这些无意义的ID。带着这些问题我们一步一步来揭晓答案。


1、有意义的ID


有一些ID是有意义的,最常见的就是我们的身份证号,一共18位。分别代表着省市县等等。在通常情况下这个ID在全国内是惟一的。他就像是一个标识符一样,唯一地代表了我们。


标识符(identifier)就是一个可以唯一识别一个对象或者物体的名称,被识别的对象可能是一些想法、物理上可数的对象或者物理上的不可数物质。它的前缀 ID 经常被用来表示身份、鉴定过程或者标识符。


因此唯一性是ID的最大特点。好比是我们的身份证号码,整个中国你找不出第二个和你一样号码的人。现在我们知道了有意义的ID通常情况下是一个标识符,唯一地代表了这个物体。现在我们把目光转到无意义的ID。


2、无意义的ID


我们的java序列化id、数据库中的自增主键、消息队列、甚至于我们的TCP通信中都会使用到这个。无意义的真正含义其实是和我们要做的事无关,也就是说这个ID数字不应该和我们的业务逻辑产生联系。


大多数业务的主键都会使用整数,它的上限一般就是 2^64,如果这些位数都用来表示记录的 ID,那么在有生之年基本上是不可能被使用完的,但是一旦我们将业务信息加入 ID,就会让原本无意义的 ID 变得有意义从而影响它的唯一性。


java序列化的那个例子,你看到serialVersionUID==xxxL,应该想不到这一串数字和这个类有什么联系吧。而且一旦有联系就有可能会出现错误。那为什么无意义的ID是有用的呢?我们举一个例子:在分布式系统中有一个分布式的 ID 生成器,Snowflake 算法会为 64 个比特的整数赋予不同的信息:


v2-d97a7bb4dc9f2a84d178deac66a2d88c_1440w.jpg

假设一台机器上一个时间单位最多只能生成 4096 个 ID,一旦超过了这个这个数量就有可能导致 ID 冲突或者乱序,从而失去其唯一性;这个算法中涉及的时间戳、数据中心标识符、机器标识符都没有办法解决唯一性的问题,哪怕这三者完全相等,此时仍然需要使用无其他意义的序列号来保证 ID 的唯一。


因此使用无意义 ID 的主要目的就是利用它的唯一性保证对象的标识符不会发生冲突,无意义 ID 的唯一作用就是保证唯一性,这能帮助我们避免业务字段可能存在潜在冲突的可能,这也提示我们想要使用联合字段构成主键时一定要深思熟虑。


3、总结


上面其实说了这么多,是想让各位有个稍微全面的了解。就像很多时候一句话讲完的事,非要BB半天。几句话总结:


对于有意义的ID,在特定场景下ID数字和业务逻辑有关,比如身份证号和每个人的唯一标识有关。


对于无意义的ID:这个ID数子一旦和业务逻辑产生联系,就有重复的可能,而且极其不安全。此时一个无意义的ID就有了唯一性。


不管有没有意义都是为了进行唯一标识,但是使用的场景不相同。


OK,今天的文章先写到这。

相关文章
|
3月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
18天前
|
存储 安全 Java
🌟Java零基础-反序列化:从入门到精通
【10月更文挑战第21天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
56 5
|
19天前
|
存储 缓存 安全
🌟Java零基础:深入解析Java序列化机制
【10月更文挑战第20天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
22 3
|
22天前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
1月前
|
存储 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第9天】在Java的世界里,对象序列化是连接数据持久化与网络通信的桥梁。本文将深入探讨Java对象序列化的机制、实践方法及反序列化过程,通过代码示例揭示其背后的原理。从基础概念到高级应用,我们将一步步揭开序列化技术的神秘面纱,让读者能够掌握这一强大工具,以应对数据存储和传输的挑战。
|
1月前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第3天】在Java编程的世界里,对象序列化与反序列化是实现数据持久化和网络传输的关键技术。本文将深入探讨Java序列化的原理、应用场景以及如何通过代码示例实现对象的序列化与反序列化过程。从基础概念到实践操作,我们将一步步揭示这一技术的魅力所在。
|
1月前
|
消息中间件 存储 Java
大数据-58 Kafka 高级特性 消息发送02-自定义序列化器、自定义分区器 Java代码实现
大数据-58 Kafka 高级特性 消息发送02-自定义序列化器、自定义分区器 Java代码实现
44 3
|
1月前
|
分布式计算 资源调度 Hadoop
Hadoop-10-HDFS集群 Java实现MapReduce WordCount计算 Hadoop序列化 编写Mapper和Reducer和Driver 附带POM 详细代码 图文等内容
Hadoop-10-HDFS集群 Java实现MapReduce WordCount计算 Hadoop序列化 编写Mapper和Reducer和Driver 附带POM 详细代码 图文等内容
89 3
|
1月前
|
Java 数据库 对象存储
Java 序列化详解
本文详细解析了Java序列化的概念与应用。通过具体实例,深入探讨了其在对象存储和传输中的作用及实现方法,帮助读者理解如何有效利用这一特性来简化数据交换,并对其实现机制有了更深入的认识。
|
22天前
|
存储 缓存 NoSQL
一篇搞懂!Java对象序列化与反序列化的底层逻辑
本文介绍了Java中的序列化与反序列化,包括基本概念、应用场景、实现方式及注意事项。序列化是将对象转换为字节流,便于存储和传输;反序列化则是将字节流还原为对象。文中详细讲解了实现序列化的步骤,以及常见的反序列化失败原因和最佳实践。通过实例和代码示例,帮助读者更好地理解和应用这一重要技术。
20 0