当前位置: 首页 > news >正文

Java中的实体类为什么要 implements Serializable?

1. 序列化和反序列化

首先来解释一下什么是序列化和反序列化:

序列化:把对象转换为字节序列的过程称为对象的序列化。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化。

  • 在 Java 和其他语言进行通信的时候,需要将对象转化成一种通用的格式例如Json( 转换成大家都认识的对象 ),从对象到 Json 字符串的转换过程就是序列化的过程,反过来, 从 Json 字符串转换成 Java 对象的过程就是反序列化的过程。
  • 当 Java 需要把一个对象的状态保存到文件或者是数据库的时候,就是数据存取的过程中的中间过程,就需要序列化。我们可以把序列化的过程理解为 "freeze",它将一个 Java 对象 freeze,然后进行存储;等到再次需要的时候,再将这个对象 "de-freeze" 就能使用了。

2. 为什么要 implements Serialzable?

  • 一个类只有实现了 Serializable 接口,它的对象才是可序列化的。因此如果要序列化某些类的对象,这些类就必须实现 Serializable 接口。而实际上,Serializable 的源码是一个空接口,没有什么具体内容,它的目的只是简单的标识一个类的对象可以被序列化
  • serialization 允许你将实现了 Serializable 接口的对象转换为字节序列,这些字节序列可以被完全存储以备以后重新生成原来的对象

3. 那么什么情况下需要实现序列化?

  • 把内存中的对象写入到硬盘。例如,你的内存不够用了,那计算机就要将内存里面的一部分对象暂时的保存到硬盘中,等到要用的时候再读入到内存中,硬盘的那部分存储空间就是所谓的虚拟内存。再例如,你要将某个特定的对象保存到文件中,隔几天在把它拿出来用,那么这时候就需要实现 Serializable 接口。
  • 使用套接字在网络上传送对象,通常情况下你可以在 server 端用获取 socket 的 outputstream inputstream,将取得的数据处理成字符串发送到客户端,然后在客户端拆分字符串,但是这样显然会降低效率,于是你可以将 server 端数据 包装 成一个 class implements Serializable,然后直接用objectoutputstream,objectinputstream 直接传递。
  • 通过 Java的 RIM(remote method invocation)传输对象。RMI 允许对象在本机上可以一样操作远程机器上的对象。当发送消息给远程对象时,就需要用到 serializaiton 机制来发送参数和接收返回值。

实体类实现序列化的目的:

  • 一是便于存储
  • 二是便于传输

像 boolean 、int、long 类型等,都是基本数据类型,数据库里面有与之对应的数据结构。从类声明来看,我们以为的没有进行序列化,其实是在声明各个不同变量的时候,由具体的数据类型帮助我们实现了序列化操作。所以就算我们不实现 serializable 依旧可以正常操作。

如果平时留意的话,我们会发现序列化操作用于存储时,一般是对于 NoSql 数据库,而在使用 Nosql 数据库进行存储时,如 redis,它就没有 varchar,int 之类的数据结构。 而在没有的情况下,我们又确实需要进行存储,那么我们就需要将对象进行序列化。

4. 为什么要显示声明 serialVersionUID

serialVersionUID 的作用是验证序列化和反序列化的过程中,对象是否保持一致。所以在一般情况下我们需要显示的声明serialVersionUID。如果接受者加载的该对象的类的 serialVersionUID 和发送者的类版本号不同的话,反序列化会爆出 InvalidClassException 错误。

什么时候会导致报出这个错误呢?例如在没有显示声明版本号的时候,先将对象进行了序列化;然后不管出于什么目的,该对象的类被修改了,哪怕仅仅是添加了一个强制转换,或者将一个 public 的属性给私有化了,都会影响版本号。此时在这个环境下用反序列化的方法读取以前序列化之后存储起来的对象是会报错的。

@Data
public class Student implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId("id")
    private Integer id;

    @TableField("name")
    private String name;

    @TableField("age")
    private Integer age;
}

相关文章:

  • 第十七天计算机视觉之光学字符识别OCR
  • Transformer架构
  • 基于SSM框架的人力资源管理系统毕业设计源码060936
  • js的基础
  • 分布式协同AI基准测试项目Ianvs:工业场景提升5倍研发效率
  • 通过Amazon EventBridge监控AWS资源发送告警至钉钉
  • Vue三种3D动态词云实现
  • 新测试人和转行测试的同学看过来 你需要知道的这几点
  • 无法将“npm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。
  • 配置mysql8.0.27教程以及注意事项
  • Tapdata 获阿里云首批产品生态集成认证,携手阿里云共建新合作
  • js的函数
  • C++——类和对象3|日期类型|Cout运算符重载|Cin运算符重载|const成员|
  • 通过Spring Data Elasticsearch操作ES
  • IPLOOK自研卫星仿真平台亮相ICCC国际通信会议
  • angular2 简述
  • AWS实战 - 利用IAM对S3做访问控制
  • Java Agent 学习笔记
  • java 多线程基础, 我觉得还是有必要看看的
  • maya建模与骨骼动画快速实现人工鱼
  • windows下使用nginx调试简介
  • 分布式任务队列Celery
  • 通过npm或yarn自动生成vue组件
  • 新书推荐|Windows黑客编程技术详解
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • ​学习一下,什么是预包装食品?​
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • # 数据结构
  • #pragam once 和 #ifndef 预编译头
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (Mac上)使用Python进行matplotlib 画图时,中文显示不出来
  • (pojstep1.3.1)1017(构造法模拟)
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (转)visual stdio 书签功能介绍
  • (转)平衡树
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET Framework .NET Core与 .NET 的区别
  • @Documented注解的作用
  • [AI]ChatGPT4 与 ChatGPT3.5 区别有多大
  • [Android Pro] listView和GridView的item设置的高度和宽度不起作用
  • [boost]使用boost::function和boost::bind产生的down机一例
  • [C#]获取指定文件夹下的所有文件名(递归)
  • [dts]Device Tree机制
  • [EFI]ASUS EX-B365M-V5 Gold G5400 CPU电脑 Hackintosh 黑苹果引导文件
  • [hdu1561] The more, The Better 【树形DP】
  • [java进阶]——方法引用改写Lambda表达式
  • [leetcode]_Symmetric Tree
  • [Oh My C++ Diary]用cout输出时后endl的使用
  • [poj] 3422 Kaka's Matrix Travels || 最小费用最大流
  • [Spring] IOC控制反转/DI依赖注入详细讲解
  • [ThinkPHP]Arr返回1
  • [UI5 常用控件] 02.Title,Link,Label
  • [UI5 常用控件] 06.Splitter,ResponsiveSplitter