首先我们说答案:实体类对象在保存在内存中的,而对于web应用程序而言,很多客户端会对服务器后台提交数据请求,如得到某种类型的商品,此时后台程序会从数据库中读取符合条件的记录,并它们打包成对象的集合,再转化为JSON,回传给前端渲染。类似请求会有很多,所以如果有这么多对象常驻内存,服务器的内存是承载不了的,此时web容器会将一个暂时没有使用的对象保存在硬盘中,这个过程我们就称之为序列化。等到需要使用时,再把再把保存在硬盘中的对象还原到内存中,这个过程,我们称之为反序列化。这种策略实质上与Windows中设置虚拟内存的做法是一样的,我们开玩笑就叫“内存不够外存凑”。而在Java中实现序列化接口是不需要实现任何方法的,因为JDK在这个接口中没定义任何方法,实现这个接口的意义只是告诉JDK当前这个类可以进行序列化。至于SerialversionUID,是用于序列化和反序列化过程中进行校验用的,一般用长整型的数据保存,用于判断当前类和反序列化后生成对象是否是同一个版本,如果还想不通我们可以举个例的,在经典的谍战片都有这么一个情节,某个情报人员从家里出门后,要在门上夹一根头发,然后出门,回来开门时再观察这根头发还在不在,如果不在了,说明家里可能来过不速之客。这个长整型的SerialversionUID与这根头发的意义是一样的,头发很细小,只要门有任何状态的改变,它就可以感知到,造成头发的掉落。由于序列化是把一个对象变成字节流,而反序列化则是将字节流程重新组织成一个类的对象,因此一个长整型的数,只有需要反序列的类有细微的变化,反序列后就会造成这个长整型数的改变,如何使用一个比较简单的int类型,有可能类发生改变,然后反序列化后这个数仍然没有改变,从而丧失校验的功能。

下面再开始制式化的解释与说明

一、什么是序列化和反序列化

把对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为对象的过程称为对象的反序列化。
  对象的序列化主要有两种用途:
  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
  2) 在网络上传送对象的字节序列。

二、实体类为什么要序列化

客户端访问了某个能开启会话功能的资源, web服务器就会创建一个与该客户端对应的HttpSession对象,每个HttpSession对象都要站用一定的内存空间。如果在某一时间段内访问站点的用户很多,web服务器内存中就会积累大量的HttpSession对象,消耗大量的服务器内存,即使用户已经离开或者关闭了浏览器,web服务器仍要保留与之对应的HttpSession对象,在他们超时之前,一直占用web服务器内存资源。

web服务器通常将那些暂时不活动但未超时的HttpSession对象转移到文件系统或数据库中保存,服务器要使用他们时再将他们从文件系统或数据库中装载入内存,这种技术称为Session的持久化。

将HttpSession对象保存到文件系统或数据库中,需要采用序列化的方式将HttpSession对象中的每个属性对象保存到文件系统或数据库中;将HttpSession对象从文件系统或数据库中装载如内存时,需要采用反序列化的方式,恢复HttpSession对象中的每个属性对象。所以存储在HttpSession对象中的每个属性对象必须实现Serializable接口。

三、Mybatis为何要求持久层的javabean序列化?

MyBatis使用SerializedCache序列化缓存来实现可读写缓存类,并通过序列化和反序列化来保证通过缓存获取数据时,得到的是一个新的实例。如果配置为只读缓存,MyBatis就会使用Map来存储缓存值,这种情况下,从缓存中获取的对象就是同一个实例。

MyBatis中配置缓存时,缓存元素<cache>有个readOnly属性,readOnly属性可以被设置为 true 或 false。只读缓存将对所有调用者返回同一个实例,因为对象没有进行序列化,所以速度最快。可写的缓存将通过序列化来返回一个缓存对象的拷贝。因为对象进行了序列化,会比较慢,但是得到的都是新的对象,线程安全。默认值是 false。即Mybatis的二级缓存默认是可写的,可写缓存会使用序列化。

序列化缓存
* 先将对象序列化成2进制,再缓存,好处是将对象压缩了,省内存
* 坏处是速度慢了(因为对象需要进行序列化)

总结:Mybatis通过序列化得到对象的新实例,保证多线程安全(因为是从缓存中取数据,速度还是比从数据库获取要快)。具体说就是对象序列化后存储到缓存中,从缓存中取数据时是通过反序列化得到新的实例。

四、为什么定义SerializableID

对于JVM来说,要进行持久化的类必须要有一个标记,只有持有这个标记JVM才允许类创建的对象可以通过其IO系统转换为字节数据,从而实现持久化,而这个标记就是Serializable接口。而在反序列化的过程中则需要使用serialVersionUID来确定由那个类来加载这个对象,所以我们在实现Serializable接口的时候,一般还会要去尽量显示地定义serialVersionUID.

如果我们在序列化中没有显示地声明serialVersionUID,则序列化运行时将会根据该类的各个方面计算该类默认的serialVersionUID值。但是,Java官方强烈建议所有要序列化的类都显示地声明serialVersionUID字段,因为如果高度依赖于JVM默认生成serialVersionUID,可能会导致其与编译器的实现细节耦合,这样可能会导致在反序列化的过程中发生意外的InvalidClassException异常。因此,为了保证跨不同Java编译器实现的serialVersionUID值的一致,实现Serializable接口的必须显示地声明serialVersionUID字段。我们前面做了了一个类比 ,某个情报人员从家里出门后,要在门上夹一根头发,然后出门,回来开门时再观察这根头发还在不在,如果不在了,说明家里可能来过不速之客。这个长整型的SerialversionUID与这根头发的意义是一样的,也就是说JDK对内存对象反序列化之后,需要利用这个长整型的数与现有的类的这个同名成员进行比对,看是否相同,如果不相同则会以抛异常的方式报警,提示反序列化失败,用于提示保存在原来序列化时的对象结构与当前类的结构不相同了(有可能是反序列之前类发生改变了)。那为什么需要使用一个长整型的数来作为serialVersionUID,一个普通的int不行吗,

此外serialVersionUID字段地声明要尽可能使用private关键字修饰,这是因为该字段的声明只适用于声明的类,该字段作为成员变量被子类继承是没有用处的!有个特殊的地方需要注意的是,数组类是不能显示地声明serialVersionUID的,因为它们始终具有默认计算的值,不过数组类反序列化过程中也是放弃了匹配serialVersionUID值的要求。

什么是序列化?实体类为什么要实现序列化接口?实体类为什么要指定SerialversionUID?的更多相关文章

  1. 阶段3 1.Mybatis_03.自定义Mybatis框架_3.自定义mybatis的编码-根据测试类中缺少的创建接口和类

    先认识一下这几个类.Resources是一个class SqlSessionFactoryBuilder 创建新项目 复制相关的依赖 复制之前的代码 复制到当前项目的src下 把Mybits的依赖删除 ...

  2. Java实体对象为什么要实现Serializable接口?

    前言 Java实体对象为什么一定要实现Serializable接口呢?在学JavaSE的时候有些实体对象不实现Serializable不是也没什么影响吗? 最近在学习mybatis的时候发现,老师写的 ...

  3. 谈谈序列化—实体bean一定要实现Serializable接口?

    导读:最近在做项目的过程中,发现一个问题,就是我们最开始的时候,传递参数包括返回类型,都有map类型.但是由于map每次都要匹配key值,很麻烦.所以在之后就将参数传递和返回类型全都改成了实体bean ...

  4. 浅谈实体类为什么要实现Serializable接口?

    序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后,可以通过从存储区中读取或反序列化对象的状态,重新创 ...

  5. 接口是否可继承接口? 抽像类是否可实现(implements)接口? 抽像类是否可继承实体类(concrete class)?

    接口是否可继承接口? 抽像类是否可实现(implements)接口? 抽像类是否可继承实体类(concrete class)? 1. 接口可以继承接口. 2. 抽像类可以实现(implements)接 ...

  6. 文件夹和文件、Path类、流、序列化

    循环访问目录树 参考: http://msdn.microsoft.com/zh-cn/library/bb513869.aspx 循环访问目录树”的意思是在指定的根文件夹下,访问每个嵌套子目录中任意 ...

  7. 调试接口,返回的json数据,我定义了一个类,用来序列化,其中有一个字段定义为string 然后序列化的时候报错

    调试接口,返回的json数据,我定义了一个类,用来序列化,其中有一个字段定义为string 然后序列化的时候报错 在需要解析的类型类上加上声明 eg:

  8. java中POJO类和DTO类都要实现序列化

    java中POJO类和DTO类都要实现序列化 java中POJO类和DTO类都要实现序列化 java中POJO类和DTO类都要实现序列化 序列化:序列化是将对象转换为容易传输的格式的过程.例如,可以序 ...

  9. 二次封装Response类 | 视图类传递参数给序列化类context

    二次封装Response类 源码: class Response(SimpleTemplateResponse): """ An HttpResponse that al ...

  10. 如果你的Serializable类包含一个不可序列化的成员,会发生什么?你是如何解决的?

    任何序列化该类的尝试都会因NotSerializableException而失败,但这可以通过在 Java中 为 static 设置瞬态(trancient)变量来轻松解决. Java 序列化相关的常 ...

随机推荐

  1. 数字图像处理之直方图处理——a cute dog huang

    关于图像处理的知识,确实很棒,在此感谢:https://blog.csdn.net/mary_0830/article/details/89003488 直方图处理概念灰度级范围为[0,L-1]的数字 ...

  2. Windows 10更新报错 0x8000ffff

    Windows 10更新报错 0x8000ffff - Microsoft Community 那么您可用 "Windows 10 覆盖安装" 来修复,可参考以下步伐,连接里有视频 ...

  3. Unit mysqld.service could not be found.

    具体命令 service mysqld status systemctl status mysqld 结果 Unit mysqld.service could not be found. 查看mysq ...

  4. C# 开源NuGet插件

    ExcelDataReader  开源免费,Excel读取插件 GitHub - ExcelDataReader/ExcelDataReader: Lightweight and fast libra ...

  5. 配置中包含maven属性,在idea中本地启动无法正常获取配置

    1. 本地启动一个spring cloud 项目,无法启动 (注:测试环境正常),且控台无错误日志. 分析:debug 代码发现是配置无法获取. 查看配置获取方式 是 spring config 通过 ...

  6. vue cli 项目初始化配置

  7. drf从入门到飞升仙界 04

    序列化类常用字段和字段参数 常用字段类 #1 BooleanField BooleanField() #2 NullBooleanField NullBooleanField() #3 CharFie ...

  8. js判断数组中对象是否存在某个值

    js判断数组中对象是否存在某个值 var arr = [{ name: "回锅肉", value: "0" }, { name: "小炒肉" ...

  9. ubuntu 20.04 基于kubeadm部署kubernetes 1.22.4集群—报错解决

    一.添加node节点,报错1 注:可以提前在各node节点上修改好(无报错无需执行此项) yang@node2:~$ sudo kubeadm join 192.168.1.101:6443 --to ...

  10. [2010年NOIP普及组] 接水问题

    学校里有一个水房,水房里一共装有 m 个龙头可供同学们打开水,每个龙头每秒钟的供水量相等,均为 1. 现在有 n 名同学准备接水,他们的初始接水顺序已经确定.将这些同学按接水顺序从1到n编号,i 号同 ...