java transient


transient:not lasting long; staying somewhere only a short time.

作用

  1. 当对象被序列化时(写入字节序列到目标文件)时,transient阻止实例中那些用此关键字声明的变量持久化;当对象被反序列化时(从源文件读取字节序列进行重构),这样的实例变量值不会被持久化和恢复
  2. 类变量(用static修饰的)即使用transient修饰,也不会被序列化。

在jdk中的应用实例

ArrayList:

 /**
     * 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修饰的实例遍历,是不会序列化的呢。然而

 public static void main(String[] args) {
        ArrayList<Integer> arrayList=new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);


        /*序列话对象arrayList到a.txt文件中*/
        try {
            OutputStream outputStream=new FileOutputStream("/home/fengli/Desktop/a.txt");
            outputStream=new  ObjectOutputStream(outputStream);
            ((ObjectOutputStream) outputStream).writeObject(arrayList);

        } catch (IOException e) {
            e.printStackTrace();
        }

        //把arrayList置为null,便于反序列话
        arrayList=null;




        /*反序列话*/
        try {
            InputStream inputStream=new FileInputStream("/home/fengli/Desktop/a.txt");
            inputStream=new ObjectInputStream(inputStream);
            arrayList= (ArrayList<Integer>) ((ObjectInputStream) inputStream).readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }

        /*现在测试arrayList中是否有数据*/
        for(int i=0;i<arrayList.size();++i){
            System.out.println("arrayList.get(i) = " + arrayList.get(i));
        }

    }

运行结果:

arrayList.get(i) = 1
arrayList.get(i) = 2
arrayList.get(i) = 3
arrayList.get(i) = 4

Q:为哈子安?

因为ArrayList重写了writeObject()readObject()两个方法(mb,我idea的structure没选择show non-public,导致始终没找到这两个方法。疑惑了半天!)

源码:

 /**
     * Save the state of the <tt>ArrayList</tt> instance to a stream (that
     * is, serialize it).
     *
     * @serialData The length of the array backing the <tt>ArrayList</tt>
     *             instance is emitted (int), followed by all of its elements
     *             (each an <tt>Object</tt>) in the proper order.
     */
    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();
        }
    }

    /**
     * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
     * deserialize it).
     */
    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
            int capacity = calculateCapacity(elementData, size);
            SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, 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();
            }
        }
    }

至于jdk为什么要这样操作,请看 ArrayList中elementData为什么被transient修饰?

原因在于elementData是一个缓存数组,它通常会预留一些容量,等容量不足时再扩充容量,那么有些空间可能就没有实际存储元素,采用上诉的方式来实现序列化时,就可以保证只序列化实际存储的那些元素,而不是整个数组,从而节省空间和时间。

结论

  • transient使用来禁止序列化实例对象的。

参考文献

在Java中如何使用transient
ArrayList中elementData为什么被transient修饰?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值