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. verilog实现红黄蓝三秒灯

    代码如下 test.v文件 led.v文件 module test(); wire led_r,led_g,led_b; ; clk <= ~clk; led c1 ( .clk(clk), . ...

  2. JavaScript中的原型链和继承

    理解原型链 在 JavaScript 的世界中,函数是一等公民. 上面这句话在很多地方都看到过.用我自己的话来理解就是:函数既当爹又当妈."当爹"是因为我们用函数去处理各种&quo ...

  3. MySQL 5.6.20-enterprise-commercial的参数文件位置问题

    今天在折腾MySQL的参数文件时,突然发现MySQL 5.6.20-enterprise-commercial-advanced-log这个版本数据库的参数文件my.cnf的位置有点奇怪,如下所示: ...

  4. A Java Runtime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Eclipse. No Java virtual machine was found after searching the following locations: /usr/local/eclipse/

    linux系统下jdk是已经安装好的情况之下软件出现 A Java Runtime Environment (JRE) or Java Development Kit (JDK) must be av ...

  5. mssql 系统函数-字符串函数专题--字符串函数大全

    mssql 系统函数 字符串函数 substring 功能简介 mssql 系统函数 字符串函数 stuff 功能简介 mssql 系统函数 字符串函数 str 功能简介 mssql 系统函数 字符串 ...

  6. ASP.NET MVC概述及第一个MVC程序

    一.ASP.NET 概述        1. .NET Framework 与 ASP.NET                .NET Framework包含两个重要组件:.NET Framework ...

  7. MongoDB数据库简单操作

    之前学过的有mysql数据库,现在我们学习一种非关系型数据库 一.简介 MongoDB是一款强大.灵活.且易于扩展的通用型数据库 MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数 ...

  8. Python面试题(二)【转】

    转载出处http://www.cnblogs.com/goodhacker/p/3387027.html 1.python中类方法.类实例方法.静态方法有何区别? 区别: 类方法和静态方法都可以被类和 ...

  9. openSUSE Leap 15.0 Adobe Flash Player 安装说明

    鉴于Firefox安装配置文件: mozilla_lib=file $MOZ_PROGRAM LIB=lib -bit.*(x86-|S/|PowerPC|ARM aarch64)’ &&am ...

  10. S/4 HANA中的MATDOC和MATDOC_EXTRACT

    最近做了销售和物料管理方面的一些需求,因此对S/4中的MM的数据模型有了一定的了解.目前网络已经有一些介绍物料凭证表MATDOC的文章,内容好像不是很详细,另外也没发现介绍库存变更数据表MATDOC_ ...