首先我们说答案:实体类对象在保存在内存中的,而对于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. SAP 常见函数

    *大小写转换 TRANSLATE STRING TO UPPER CASE. TRANSLATE STRING TO LOWER CASE. *前缀去零 CALL FUNCTION 'CONVERSI ...

  2. UntrimmedNets for weakly supervised action recognition and detection概述

    0.前言 相关资料: 论文 github 论文解读(CSDN) 论文基本信息: 领域:动作识别与检测 发表时间:CVPR2017(2017.5.22) 1.针对的问题 这篇论文之前的行为识别方法严重依 ...

  3. Codeforces Round #769 (Div. 2) - D. New Year Concert

    GCD + st表 + 二分 Problem - 1632D - Codeforces 题意 给出一个长度为 \(n\;(1<=n<=2*10^5)\) 的数组 \(a[i]\;(1< ...

  4. IDEA中已配置阿里镜像,但maven无法下载jar包的问题

    然后我还出现了一个问题,由于使用了HTTPS,存在着SSL证书验证的问题,因此我在IDEA中添加了一行配置: 配置如下: -Dmaven.wagon.http.ssl.insecure=true -D ...

  5. 打卡node day01--基础和fs内置模块

    一, 检查 node 版本 node -v 或 node --version 二,检查安装过的node 版本(nvm node 版本管理工具  安装链接 参考百度) nvm ls 三,切换node 版 ...

  6. 有符号数 无符号数 原码 补码 反码 java用补码表示

    计算机数字的储存分为:1.无符号数,2.有符号数 无符号数:只能表示正数.每一位数都代表2的幂次方.只有地址用无符号数,无符号数不进行算术操作,之进行指针的加减.地址并不会造成错误的结果,而是产生一个 ...

  7. npm 包管理器run命令理解

    npm run命令需和项目根目录下的package.json文件配合使用: npm run执行package.json文件的"scripts"属性中定义的命令,如下例: {   & ...

  8. MySQL索引 及 EXPLAIN

    1.索引长度计算: 1.索引字段,没有设置NOT NULL,则需要加一个字节. 2.定长字段:tinyiny占1个字节.int占4个字节.bitint占8个字节.date占3个字节.datetime占 ...

  9. WDA学习(19):UI Element:Table使用

    1.12 UI Element:Table使用 1.Table Filter and Sort 1.1创建Context节点; NODE_SFLIGHT, FILTER_COL:CARRID,CONN ...

  10. Google Chrome 离线安装包官方下载

    我们参照 Google Chrome帮助中的<下载和安装 Google Chrome>,在这里找到官方最新版离线安装包的下载地址:备用 Chrome 安装程序,历史版本请通过版本号的方式下 ...