transient与种类化

transient与序列化

金沙手机APP,transient的作用:

修饰实力域,使其从一个类的默认序列化形式中省略(即默认序列化方式不对该字段做写与读
存取操作)

 

应用场景:

  1. 业务需要,不宜做序列化
    如银行密码等 信息不希望在网络和磁盘等地方存储,所以可以用transient
    声明,从而保证相应信息无法从磁盘读取。(此例源于网上观点,个人不太赞同)

    1. 默认的序列化方式不适合,采用自定义序列化的方式
      例hashMap中对元素的存储。java 7中hashMap元素的存储结构为 表
      (table)+
      链(结点构成的链)的存储结构。其中根据hash(key)求的对应元素在table的索引,并将元素插入此索引处的链表。

      其中的实例域table 即为transient

          /**
           * The table, resized as necessary. Length MUST Always be a power of two.
           */
          transient Entry[] table = (Entry[]) EMPTY_TABLE;
      

       

      那么问题来了,既然table中存储着hashMap中的元素信息,为什么不序列化?

       

      答:不是不序列化,而是不采用默认的序列化。

      由于table中元素信息是我们存取关注的,而非table的结构,所以能合理的完成table中所有信息的存取是关键。

      鉴于table结构过于复杂(其中的链表结构为Entry
      结点构成的链表),若采用默认的序列化方式,会将table的完整结构(包括各链表)镜像一份,如此以来带来一下弊端:

      1. 不仅需要消化大量时间遍历table结构

      2. 占用较多的存储空间

      3.
      默认序列化对对象图做递归遍历当表过大时会发生堆栈溢出,所以避免使用默认的序列化方式。

       

      hashMap中采用序列化存储过程中遍历table中元素,并逐一序列化储存。而在序列化读取过程中,根据读出数值还原表结构的方式来完成,从而提高序列化的质量。过程如下:

      private void writeObject(java.io.ObjectOutputStream s)
              throws IOException
          {
              // Write out the threshold, loadfactor, and any hidden stuff
              s.defaultWriteObject();
               ….
                //自定义完成table中信息的存储
              // Write out keys and values (alternating)
              if (size > 0) {
                  for(Map.Entry e : entrySet0()) {
                      s.writeObject(e.getKey());
                      s.writeObject(e.getValue());
                  }
              }
          }
      
          private static final long serialVersionUID = 362498820763181265L;
      
          /**
           * Reconstitute the {@code HashMap} instance from a stream (i.e.,
           * deserialize it).
           */
          private void readObject(java.io.ObjectInputStream s)
               throws IOException, ClassNotFoundException
          {
              // Read in the threshold (ignored), loadfactor, and any hidden stuff
              s.defaultReadObject();
              ...
              //依次读取,并还原表结构
              // Read the keys and values, and put the mappings in the HashMap
              for (int i = 0; i < mappings; i++) {
                  K key = (K) s.readObject();
                  V value = (V) s.readObject();
                  putForCreate(key, value);
              }
          } 
      
    如此,当自定义中实例域存储机构将复杂,默认序列化方式无法胜任时,可以声明为transient,并自定义完成该字段中信息的序列化。

transient的作用:
修饰实力域,使其从一个类的默认序列化形式中省略(即默认序列化方式不对该字段做写与读
存取操作)…

相关文章