transient用来表示一个域不是该对象序行化的一部分,当一个对象被序行化的时候,transient修饰的变量不会被序列化

  ArrayList的动态数组elementData被transient  修饰的  那么岂不是反序列化后的ArrayList丢失了原先的元素, 其实不然.  ArrayList在序列化的时候会调用writeObject,反序列化时调用readObject 也就是自定义序列化

  • 为什么要自定义序列化?

    • 因为ArrayList数组elementData中有未使用的空间 ,如果没有使用的空间也序列化,势必会影响性能.
  • 基本概念

    序列化:将一个对象转换成一串二进制表示的字节数组,通过保存或转移这些字节数据来达到持久化的目的。
    反序列化:将字节数组重新构造成对象。

  • 默认序列化

  序列化只需要实现java.io.Serializable接口就可以了。序列化的时候有一个serialVersionUID参数,Java序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。 在进行反序列化,Java虚拟机会把传过来的字节流中的serialVersionUID和本地相应实体类的serialVersionUID进行比较, 如果相同就认为是一致的实体类,可以进行反序列化,否则Java虚拟机会拒绝对这个实体类进行反序列化并抛出异常。

  • serialVersionUID有两 种生成方式:

    1、默认的1L

    2、根据类名、接口名、成员方法以及属性等来生成一个64位的Hash字段

  如果实现 java.io.Serializable接口的实体类没有显式定义一个名为serialVersionUID、类型为long的变量时,Java序列化 机制会根据编译的.class文件自动生成一个serialVersionUID,如果.class文件没有变化,那么就算编译再多 次,serialVersionUID也不会变化。换言之,Java为用户定义了默认的序列化、反序列化方法,其实就是ObjectOutputStream的defaultWriteObject方法和ObjectInputStream的defaultReadObject方法。

  • 从以上对于序列化后的二进制文件的解析,我们可以得出以下几个关键的结论:

    1、序列化之后保存的是类的信息
    2、被声明为transient的属性不会被序列化,这就是transient关键字的作用
    3、被声明为static的属性不会被序列化,这个问题可以这么理解,序列化保存的是对象的状态,但是static修饰的变量是属于类的而不是属于变量的,因此序列化的时候不会序列化它

  • 手动指定序列化过程:

    Java并不强求用户非要使用默认的序列化方式,用户也可以按照自己的喜好自己指定自己想要的序列化方式----只要你自己能保证序列化前后能得到想要的数据就好了。手动指定序列化方式的规则是:

    进行序列化、反序列化时,虚拟机会首先试图调用对象里的writeObject和readObject方法,进行用户自定义的序列化和反序列化。如果没有这 样的方法,那么默认调用的是ObjectOutputStream的defaultWriteObject以及ObjectInputStream的 defaultReadObject方法。换言之,利用自定义的writeObject方法和readObject方法,用户可以自己控制序列化和反序列 化的过程。这是非常有用的。

  • 比如:

    ArrayList的 elementData、HashMap的table

    /**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
transient Object[] elementData; // non-private to simplify nested class access

    transient  当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中

    显然诸如 ArrayList在初始化的时候 就有空间了, 我们在操作list的时候 会存在未使用的空间,如果在序列化的时候把未使用的也序列化就不合理了

    所以ArrayList有writeObject和readObject方法自定义了序列化与反序列化:

    private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject(); // Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size); // Write out all elements in the proper order.
//只序列化了被使用的数据
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
} if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
} private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA; // Read in size, and any hidden stuff
s.defaultReadObject(); // Read in capacity
s.readInt(); // ignored if (size > 0) {
// be like clone(), allocate array based upon size not capacity
ensureCapacityInternal(size); Object[] a = elementData;
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
}
  • 序列化并不安全,因此有些场景下我们需要对一些敏感字段进行加密再序列化
  • 复杂序列化情况总结

    虽然Java的序列化能够保证对象状态的持久保存,但是遇到一些对象结构复杂的情况还是比较难处理的,最后对一些复杂的对象情况作一个总结:
      1、当父类继承Serializable接口时,所有子类都可以被序列化
      2、子类实现了Serializable接口,父类没有,父类中的属性不能序列化(不报错,数据丢失),但是在子类中属性仍能正确序列化
      3、如果序列化的属性是对象,则这个对象也必须实现Serializable接口,否则会报错
      4、反序列化时,如果对象的属性有修改或删减,则修改的部分属性会丢失,但不会报错
      5、反序列化时,如果serialVersionUID被修改,则反序列化时会失败

序列化与ArrayList 的elementData的修饰关键字transient的更多相关文章

  1. Java 中关键字transient引出序列化与反序列化

    一:transient(临时的)关键字 1.transient关键字只能修饰变量,而不能修饰方法和类.注意,本地变量是不能被transient关键字修饰的. 2.被transient关键字修饰的变量不 ...

  2. 对访问修饰关键字public, protected, internal and private的说明

    对访问修饰关键字public, protected, internal and private的说明1.msdn: Internal types or members are accessible o ...

  3. c语言学习之基础知识点介绍(十八):几个修饰关键字和内存分区

    一.几个修饰关键字 全局变量: 全局变量跟函数一样也分为声明和实现.如果是全局变量,实现在它调用之后,那么需要在调用之前进行声明.注意:全局变量的声明只能写在函数外,写在函数就不是全局变量了而是局部变 ...

  4. 关于java的关键字 transient

    我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,Java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable ...

  5. Java中的关键字 transient

    先解释下Java中的对象序列化 在讨论transient之前,有必要先搞清楚Java中序列化的含义: Java中对象的序列化指的是将对象转换成以字节序列的形式来表示,这些字节序列包含了对象的数据和信息 ...

  6. 【JSON 注解】JSON循环引用2----JSON注解@JsonIgnoreProperties+JAVA关键字transient+后台对象与JSON数据的格式互相转化

    接着来说这个JSON循环引用的问题: 关于JSON格式的转化,其实关键就是这几个依赖: <!-- json --> <!-- 1号 --> <dependency> ...

  7. Java关键字:transient,strictfp和volatile简介

    关键字:transient 使用对象:字段 介绍:transient说明一个属性是临时的,不会被序列化. 当对象进行序列化(Serializable)过程时候,有一些属性的状态是瞬时的,这样的对象是无 ...

  8. java 关键字 transient

    一个对象实现了Serilizable 接口,该对象就可以被序列化. 然而在实际开发工程中,我们会遇到,这个类的有些属性不需要序列化,比如包含用户的敏感信息(如密码),为了安全起见,不希望在网络操作(主 ...

  9. java关键字-transient

    java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持. Java的serialization提供了一种持久化对象实例的机制.当持久化对象时,可能有 ...

随机推荐

  1. 不需要再手写 onSaveInstanceState 了,因为你的时间非常值钱

    如果你是一个有经验的 Android 程序员,那么你肯定手写过许多 onSaveInstanceState 以及 onRestoreInstanceState 方法用来保持 Activity 的状态, ...

  2. 适用于VS C++环境的注释代码段,可以让你的代码被使用时有高可读性的注释

    编码时,在对高级语言(C#/VB etc)函数的访问时,经常会有很明确的函数功能提示,参数提示,与返回值提示.微软的VisualStudio C++集成开发环境同样有这样的功能,只是常见开源的代码很少 ...

  3. php json_encode中提示的中文总是返回"\u767b\u5f55\u6210\u529f\uff01"的解决办法

    最近在练习使用 php 写一些简单的接口,但是在返回的消息中,如果有中文,在测试后总是返回: {"resultCode":200,"message":" ...

  4. Java:字节流和字符流(输入流和输出流)

    本文内容: 什么是流 字节流 字符流 首发日期:2018-07-24 什么是流 流是个抽象的概念,是对输入输出设备的抽象,输入流可以看作一个输入通道,输出流可以看作一个输出通道. 输入流是相对程序而言 ...

  5. ELk(Elasticsearch, Logstash, Kibana)的安装配置

    目录 ELk(Elasticsearch, Logstash, Kibana)的安装配置 1. Elasticsearch的安装-官网 2. Kibana的安装配置-官网 3. Logstash的安装 ...

  6. 确认是否是因为做了物理I/O而导致的性能不佳

    要获取语句是否进行了I/O,需要打开set statistics on 和set statistics on.

  7. 自动化测试基础篇--Selenium获取元素属性

    摘自https://www.cnblogs.com/sanzangTst/p/8375938.html 通常在做断言之前,都要先获取界面上元素的属性,然后与期望结果对比. 一.获取页面title 二. ...

  8. 【转】win2008 中iis7设置404页面但返回状态200的问题解决办法

    今天根据SEO反馈,某个站点中设置的404页面返回的http状态为200.通过站长工具进行查询,发现返回的状态确实为200. 通过彻查问题,发现这个网站的服务器环境为windows2008 服务器为i ...

  9. 前端数据库——WebSQL和IndexedDB

    一.WebSQL WebSQL是前端的一个独立模块,是web存储方式的一种,我们调试的时候会经常看到,只是一般很少使用.并且,当前只有谷歌支持,ie和火狐均不支持. 我们对数据库的一般概念是后端才会跟 ...

  10. 【HNOI2016】树

    [HNOI2016]树 题目描述 每一个复制过来的子树(我们称为一个树团)有用的只有需要被访问的节点,包括根,根的父亲,要询问的点.我们只需要求出这些点到其所在树团根的距离以及倍增数组就好了. 需要讨 ...