我把序列化玩成了这样,吊锤了一波面试官

支付宝面试:什么是序列化,怎么序列化,为什么序列化,反序列化会遇到什么问题,如何解决? 遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题 什么叫序列化和反序列化 作用。为啥要实现这个 Serializable 接口,也就是为啥要序列化 serialVersionUID 这个的值到底是在怎么设置的,有什么用。有的是1L,有的是一长串数字,迷惑ing。 我刚刚见到这个关键字 Serializable 的时候,就有如上的这么些问题。 在处理这个问题之前,你要先知道一个问题,这个比较重要。这个Serializable接口,以及相关的东西,全部都在 Java io 阅读详情

我们都知道,新建一个对象的时候实现 Serializeable 接口,但为什么要这么做?什么时候这样子做?这样子做会不会出现幺蛾子?阿粉一个三连差点把自己都问懵逼了……

那接下来,大家就和阿粉一起简单了解一下这个知识点吧……

序

序列化的定义是:将一个对象编码成一个字节流(I/O);而与之相反的操作被称为反序列化。

序列化的目的是为了方便数据的传递以及存储到磁盘上(把一个Java对象写入到硬盘或者传输到网路上面的其它计算机,这时我们就需要将对象转换成字节流才能进行网络传输。对于这种通用的操作,就出现了序列化来统一这些格式)。

简单来说序列化就是一种用来处理对象流的机制。将对象转化成字节序列后可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。

使用场景:所有可在网络上传输的对象都必须是可序列化的,比如RMI(remote method invoke,即远程方法调用),传入的参数或返回的对象都是可序列化的,否则会出错;所有需要保存到磁盘的java对象都必须是可序列化的。比如 Redis 将对象当做字符串存储的时候,如果对象实现了序列化,则只需要将对象直接存储即可(java会自动将对象转换成序列化后的字节流);否则需要自己将对象转换成 json 字符串存储,不过 json 字符串相对更加节省内存空间一些。

通常建议:程序创建的每个JavaBean类都实现 Serializeable 接口。但是实现 Serializeable 接口也需要小心谨慎。正如《Effective Java》中第 74 条提到的那样:

如何实现序列化

在 Java 中,只要一个类实现了 java.io.Serializable 接口,它就可以被序列化(枚举类也可以被序列化)。

例如:每个枚举类型都会默认继承类java.lang.Enum,而Enum类实现了Serializable接口,所以枚举类型对象都是默认可以被序列化的。

// DeletedEnum 类,表示删除状态
@Getter
@AllArgsConstructor
public enum DeletedEnum {
	NO_DELETED(0,"未删除"),
	DELETED(1,"已删除");


	public final Integer status;
	public final String name;
}

下图是 java.lang.Enum 类:

而一个普通的类想实现序列化,只需要实现 Serializable 接口即可:

@Data
public class User implements Serializable {
    //序列化版本号
    private static final long serialVersionUID = 1111013L;


    transient private String name;
    private int age;


    public static void main(String[] args) {
        User user = new User();
        user.setAge(12);
        user.setName("小路飞");
        System.out.println(user);
    }
}

输出结果如下:

User(name=小路飞, age=12)

那为什么一个类实现了 Serializable 接口,它就可以被序列化呢?

这是因为它使用 ObjectOutputStream 来持久化对象到文件中,使用了 writeObject 方法,该方法又调用了如下方法:

    /**
     * Underlying writeObject/writeUnshared implementation.
     */
    private void writeObject0(Object obj, boolean unshared) throws IOException {
        ……
        // remaining cases
        if (obj instanceof String) {
            writeString((String) obj, unshared);
        } else if (cl.isArray()) {
            writeArray(obj, desc, unshared);
        } else if (obj instanceof Enum) {
            writeEnum((Enum<?>) obj, desc, unshared);
        } else if (obj instanceof Serializable) {
            writeOrdinaryObject(obj, desc, unshared);
        } else {
            if (extendedDebugInfo) {
                throw new NotSerializableException(
                    cl.getName() + "\n" + debugInfoStack.toString());
            } else {
                throw new NotSerializableException(cl.getName());
            }
        }
        ……
    }

从上述代码可知,如果被写对象的类型是String,或数组,或 Enum,或 Serializable,那么就可以对该对象进行序列化,否则将抛出 NotSerializableException。

即:String 类型的对象、枚举类型的对象、数组对象,都是默认可以被序列化的,并生成默认的序列化版本号。

我看网上的资料都有讲使用 Externalizable 接口和使用 transient 关键字来实现序列化的方法,但阿粉感觉用的不多,所以在这里就不过多的赘述了,况且它们其实都是基于 Serializable 接口实现的序列化。

如何自动生成序列化版本号

idea IDE

安装 serialVersionUID 插件即可。

eclipse

一般来说有两种生成方式:

  • 一个是默认的1L,比如:private static final long serialVersionUID = 1L;

  • 一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段。实现序列化后,类名上会出现黄色波浪下划线,选择第一项,添加已生成的串行版本标识即可自动生成一个。

序列化版本号的用处

在 java.io.Serializable 的文档中的解释是这样的:

大致意思是如下:

因为反序列化必须拥有 class 文件,但随着项目的升级,class 文件也会升级,序列化怎么保证升级前后的兼容性呢?

序列化运行时与每个可序列化的类关联一个版本号,称为 serialVersionUID,在反序列化期间使用该版本号来验证序列化对象的发送者和接收者是否已加载了该对象的与序列化兼容的类。如果接收方已为该对象加载了一个与相应发送方类具有不同的 serialVersionUID 的类,则反序列化将导致 InvalidClassException。可序列化的类可以通过声明一个名为 serialVersionUID 的字段来显式声明其自己的 serialVersionUID,该字段必须是静态的,最终的且类型为 long:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

只要版本号相同,即使更改了序列化属性,对象也可以正确被反序列化回来。

@Data
public class User implements Serializable {
    //序列化版本号    
    private static final long serialVersionUID = 1111013L;
    private String name;
    private int age;
}

如果反序列化使用的 class 的版本号与序列化时使用的不一致,反序列化会报 InvalidClassException 异常。

如果可序列化的类未明确声明 serialVersionUID ,则序列化运行时将根据该类的各个方面为该类计算默认的 serialVersionUID 值,如Java(TM)对象序列化规范中所述。但是,强烈建议所有可序列化的类显式声明 serialVersionUID 值,因为默认的 serialVersionUID 计算对类详细信息高度敏感,而类详细信息可能会根据编译器的实现而有所不同,因此可能在反序列化期间导致意外的 InvalidClassExceptions。

而且,默认值不利于 jvm 间的移植,可能class文件没有更改,但不同 jvm 可能计算的规则不一样,这样也会导致无法反序列化。

因此,为了保证不同Java编译器实现之间的 serialVersionUID 值一致,可序列化的类必须声明一个显式的 serialVersionUID 值。强烈建议显式 serialVersionUID 声明在可能的情况下使用 private 修饰符,因为此类声明仅适用于立即声明的类 serialVersionUID字段作为继承成员不起作用。

最后,使用默认机制在序列化对象时,不仅会序列化当前对象,还会对该对象引用的其它对象也进行序列化,同样地,这些其它对象引用的另外对象也将被序列化,以此类推。所以,如果一个对象包含的成员变量是容器类对象,而这些容器所含有的元素也是容器类对象,那么这个序列化的过程就会较复杂,开销也较大。

参考

  • https://www.cnblogs.com/kubixuesheng/p/10350523.html

  • https://stackoverflow.com/questions/285793/what-is-a-serialversionuid-and-why-should-i-use-it

  • https://juejin.im/post/5ce3cdc8e51d45777b1a3cdf

  • 《Effective Java》中文版第二版

< END >

如果大家喜欢我们的文章,欢迎大家转发,点击在看让更多的人看到。也欢迎大家热爱技术和学习的朋友加入的我们的知识星球当中,我们共同成长,进步。

什么是序列化与反序列化?一文彻底搞懂核心原理与应用 序列化(Serialization)是指将 Java 对象转换为字节序列的过程,以便进行网络传输、持久化存储或进程间通信。反序列化(Deserialization)则是将字节序列恢复为 Java 对象的过程。这类题目常用于考察候选人对 Java I/O 系统、JVM 内存模型、对象状态管理、甚至是安全漏洞(如反序列化漏洞)的掌握情况。✅答题要点:对象 → 字节流(用于网络传输或持久化)字节流 → 对象(恢复原始状态)📌将对象写入文件或数据库(持久化)在网络中传输对象(如 RPC 调用) 阅读详情

相关推荐

非球面检测

摘要:非球面镜检测主要采用干涉法,包括零位补偿和非零位补偿两种方式。零位补偿通过透镜组完全校正像差,精度达1%波长,但设计复杂成本高;非零位补偿利用部分像差补偿降低波前斜率,适用于规则非球面。折射-衍射混合补偿镜能同时校正多种像差。实际检测中可采用物理补偿镜或动态CGH加载方案,光路设计需运用坐标断点和多重结构技术实现复杂光路建模。不同方法各具优势,需根据检测需求选择合适方案。

Zhaxibamao的博客 2112

序列化和反序列化

我以前确实对序列化,乃至现在也是不是很熟悉,有时候查找资料,但依旧懵懵懂懂,不过还好遇到一个博主,确定写的挺好的,链接会放再底部 废话不多说,先看官网定义: 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。 序列化主要有两个用途 把对象的字节序列永久保存到硬盘上,通常存放在一个文件中(序列化对象) 在网络上传送对象的字节序列(网络传输对象)

lei_gentle的博客 5万+

Quantum Espresso Hands-On实战训练(四)——PDOS计算与轨道分析

本文详细介绍了Quantum Espresso中PDOS计算与轨道分析的实战方法,重点解析了PDOS在材料电子结构研究中的核心价值,包括原子级分辨率、轨道级解析和自旋极化分析。通过具体案例和操作步骤,帮助读者掌握从输入文件准备到结果解读的全流程,并提供了高级分析技巧和疑难问题解决方案。

weixin_29211309的博客 504

【超详细讲解】什么是序列化和反序列化?

序列化是将对象的状态转换为可存储或可传输格式的过程。对象在内存中一般以特定的数据结构(指针、引用、哈希表、链表等)存在,直接传输内存数据是不可靠的(不同机器架构不同、数据对齐不同、指针无意义等问题)。所以我们需要将对象转换成连续的字节流(或标准格式的文本),使得:可以写入磁盘文件可以通过网络发送到远端可以被其他进程或设备正确解析简单来说,序列化是让数据“离开内存,去旅行”的必备装备。反序列化就是序列化的逆过程。把收到的字节流或文本格式数据,还原成内存中的对象或数据结构,供程序继续操作。

m0_53518956的博客 1万+

GLMM(广义线性混合模型)原理以及分析步骤

广义线性混合模型(GLMM)是生态与进化研究中处理非正态数据的定制化工具,能同时分析固定效应和随机效应。它通过链接函数连接响应变量与预测因子,支持二项分布、泊松分布等非正态数据。研究流程包括:明确分析目标(固定效应影响与随机效应方差)、选择合适变量与分布、数据验证、参数估算(需根据模型复杂度选择PQL、拉普拉斯近似等方法)及模型优化(检验过离散与残差,通过信息准则或假设检验筛选最优模型)。GLMM能有效解决传统方法无法处理的"伪重复"和推广性问题,为复杂生物数据提供可靠分析框架。

wewil_lwin的博客 4998

华为2019秋招笔试Java实现(2)

华为2019秋招笔试Java实现(2) 笔试日期2019年8月14日 第二题(200分) 题目描述 某程序员小A,有一种表格数据需要存储在文件中。表格中的每一行,由若干个字段组成,每个字段可以是整数或字符串(字符串只包含数字、字母以及特殊字符!@#%^&*()",)。小A设计了一种存储格式,采用文本的方式对表格数据进行存储。文本文件中的每一行,代表了表格数据中的一行数据。具体格式描述如下: 1、采用逗号分隔不同的字段(逗号前后无空格); 2、数字直接采用10进制的文本存储; 3、字符串的存储规则如下

hewhys的博客 1549

一文带你了解序列化与反序列化基本原理与操作

序列化是指将对象转换为字节序列的过程,以便于存储或传输。在序列化过程中,对象的状态信息将被转换为字节流,可以保存到文件中或通过网络传输给其他计算机。反序列化则是将字节序列恢复为对象的过程。通过反序列化操作,可以从存储的字节流中还原对象的状态。这使得可以在程序重启后,读取保存的字节流并重新构造对象,从而快速恢复对象的状态。在分布式系统中,可以将对象进行序列化,并在不同的计算机之间进行传输。接收方可以通过反序列化操作将字节序列转换为可操作的对象。某些远程通信框架使用序列化和反序列化来实现远程方法调用。

m0_68987535的博客 1万+

L2-028 秀恩爱分得快(测试点3说明)

古人云:秀恩爱,分得快。互联网上每天都有大量人发布大量照片,我们通过分析这些照片,可以分析人与人之间的亲密度。如果一张照片上出现了 K 个人,这些人两两间的亲密度就被定义为 1/K。任意两个人如果同时出现在若干张照片里,他们之间的亲密度就是所有这些同框照片对应的亲密度之和。下面给定一批照片,请你分析一对给定的情侣,看看他们分别有没有亲密度更高的异性朋友?

daybreak_alonely的博客 1413

面试官:您能说说序列化和反序列化吗?是怎么实现的?什么场景下需要它?

序列化和反序列化是Java中最基础的知识点,也是很容易被大家遗忘的,虽然天天使用它,但并不一定都能清楚的说明白。我相信很多小伙伴们掌握的也就几句概念、关键字(Serializable)而已,如果深究问一下序列化和反序列化是如何实现、使用场景等,就可能不知所措了。在每次我作为面试官,考察Java基础时,通常都会问到序列化、反序列化的知识点,用以衡量其Java基础如何。当被问及Java...

xcbeyond|疯狂源自梦想,技术成就辉煌 7146

WPF的基础设施:XAML基础语法

XAML是WPF的核心标记语言,采用XML语法实现界面与逻辑分离。其基础语法包括:1)控件声明方式(特性语法和属性元素语法);2)x:Name与Name的区别(适用范围和编译行为);3)注释规范与代码折叠技巧;4)实用特性如属性继承、附加属性等。文章还提供了常见错误排查方法,建议通过实践练习掌握XAML开发技巧。全文系统介绍了XAML的核心语法与应用场景,是WPF开发者的基础学习指南。

Hare的博客 1758

Arduino、ESP32驱动TEMT6000传感器(光照传感器篇)

TEMT6000是一个三极管类型的光敏传感器,其光照强度和基极的电流成正比。用起来也相当简单,可以简单的连接该传感器的基极到模拟电压输入,通过简单的检测电压值就可以判断当前的光照强度。

不脱发的程序猿 4233

面试官:Java Optional 为什么设计成不可序列化的?

你知道的越多,不知道的就越多,业余的像一棵小草!你来,我们一起精进!你不来,我和你的竞争对手一起精进!编辑:业余草推荐:https://www.xttblog.com/?p=5138面试...

xmt1139057136的专栏 921

2024年下半年网络规划设计师论文真题

3、深入论述自身参与的工业网络是如何实施的,为实现制造业的智能化,如何实现数据的跨系统互通,促进各种工业数据的充分流动和无缝集成以及数据安全。3、结合自身参与的网络建设,详细叙述针对该网络“去NAT”的规划和设计方案。4、在实施过程中遇到的问题以及如何处理,项目实施后的效果和评价。2、大型园区网络“去NAT”改造和业务融合的整体架构。1、“网络去NAT”对推进ipv6演进和应用的意义。4、改造过程中遇到的问题及解决方案。2、简要叙述自身参与的制造网络建设。1、网络规划在智能制造中的意义。

鹿鸣天涯 2371

面试官:详细说说你对序列化的理解

前面引入游戏的例子是为了让大家生动地理解什么是序列化和反序列化。序列化是指将对象实例的状态存到存储媒体的过程反序列化是指将存储在存储媒体中的对象状态装换成对象的过程把对象转化为可传输的字节序列过程反序列化:把字节序列还原为对象的过程。

sjkflw121150的博客 882

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

面试官:说说你对序列化的理解

不过,强烈建议 所有可序列化类都显式声明 serialVersionUID 值,原因是计算默认的 serialVersionUID对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化过程中可能会导致意外的 InvalidClassException。安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行RMI传输等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的;真相当然还是在源码里。

m0_69632475的博客 737

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

面试官:看你简历说精通序列化与反序列化

12 | 序列化与反序列化:如何通过网络传输结构化的数据? 2019-08-17 李玥 你好,我是李玥。 最近有一些同学留言说,感觉这几节课讲的内容和消息关系不大。这里我解释一下,因为我们课程其中的一个目的,是让同学们不仅会使用消息队列,还可以通过对消息队列的学习,在代码能力上有一个提升,具备“造轮子”的能力。这样,你对消息队列的理解才能足够的深入,而不只是浮于表面。如果你细心可能也会发现,很多大厂在面试时,提到消息队列的问题,也不会仅仅局限在消息队列的使用上,他更多的会考察“你为什么这么实现”。 所以在进

JavaEdge全是干货的技术号 3168

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

面试官可能问到的序列化和反序列化

序列化和反序列化不仅在java程序员日常的工作中非常的重要,这同样也是HR通常在面试时向面试者提出的问题,本篇文章从面试题出发,完整的讲解实现序列化和反序列的步骤和面试中常用问题的解答

小白的程序猿 549

反序列化漏洞详解(一)

反序列化过程: 构造完的poc 反序列化给一个对象A 告诉这个对象你是index类的你里面有个test的属性 并且这个属性属于evil类的 evil(test对象)里的值test2为system(dir) 因为是反序列化在反序列化结束的时候会自动执行index类(对象A)中的__destruct()魔术方法 从而执行action。在类中直接声明的变量成为成员属性(也可以成为成员变量),可以在类中声明多个变量,即对象中可以有多个成员属性,每个变量都存储对象不同的属性信息。通过调用的方法,触发代码执行。

m0_72125469的博客 1700

面试官:详细说说你对序列化的理解?

前面引入游戏的例子是为了让大家生动地理解什么是序列化和反序列化。序列化是指将对象实例的状态存到存储媒体的过程反序列化是指将存储在存储媒体中的对象状态装换成对象的过程把对象转化为可传输的字节序列过程反序列化:把字节序列还原为对象的过程。

mf97532的博客 776

面试官:什么是 Java 序列化与反序列化?

候选人是否能在实际开发中(如 RPC 调用、对象缓存、持久化存储)正确应用序列化,并了解其性能、安全方面的局限性以及主流的替代方案(如 JSON、Protocol Buffers)。:高效的二进制序列化方案,跨语言、高性能、体积小、有清晰的模式定义(Schema),是现代 RPC 框架(如 gRPC)和大数据系统的首选。:在新项目中,除非有强兼容性需求,否则应优先考虑使用 JSON(如 Jackson/Gson)或高效的二进制协议(如 Protobuf)。在反序列化时,JVM 会比较字节流中的。

犬小哈 353

fegin调用为什么要序列化_面试官:您能说说序列化和反序列化吗?

序列化和反序列化是Java中最基础的知识点,也是很容易被大家遗忘的,虽然天天使用它,但并不一定都能清楚的说明白。我相信很多小伙伴们掌握的也就几句概念、关键字(Serializable)而已,如果深究问一下序列化和反序列化是如何实现、使用场景等,就可能不知所措了。 在每次我作为面试官,考察Java基础时,通常都会问到序列化、反序列化的知识点,用以衡量其Java基础如何。当被问及Java序列化是什么...

weixin_39639550的博客 193
上一篇: 谁再说端午节不能说节日快乐,你就把这篇文章甩给他
下一篇: SpringBoot整合Redis做缓存,实战分享
javageektech
博客等级 码龄7年 306粉丝 433原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值