Java集合的序列化

本文深入探讨了Java集合如ArrayList、HashMap等如何实现序列化,揭示了transient关键字的作用及其实现细节。通过源码分析,阐述了集合类在序列化过程中如何避免不必要的空间浪费,同时保持序列化的完整性和效率。
摘要由CSDN通过智能技术生成

Java集合是如何序列化的?
前不久,我在读到TreeSet的源码时看到了如下方所示的一行代码,从这行代码中可以了解到两个很重要的信息:第一,TreeSet是通过NavigableMap来实现的(默认情况下m = new TreeMap<E,Object>(),因此默认情况下TreeSet就是通过TreeMap来实现的);第二,mtransient

private transient NavigableMap<E,Object> m;

mtransient???什么情况???那序列化之后TreeSet中不是啥都没有了吗???
紧接着还有更大的发现:

ArrayList

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    ...
    transient Object[] elementData; 
    ...
}

HashMap

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {
    ...
    transient Node<K,V>[] table;
    transient Set<Map.Entry<K,V>> entrySet;
    ...
}

其它集合类也都出现了这样的情况,不一一赘述。
集合中用来存储元素的数组无一例外都加上了Java关键字transient,这意味着这些量都将不做序列化,但通过常识我们也能知道,集合是可以序列化的,而且集合都实现了Serializable 接口,那么集合又将是如何序列化的?那Java设计者又为什么要使用transient 关键字呢?

首先解释为什么要使用transient关键字的问题,以ArrayList为例,elementData是一个对象数组,一般情况下该数组不会存满数据,也就是List的size和capacity一般情况下并不相等,因此全序列化的会浪费空间以及增加不必要的开销。

那么集合如何序列化?
集合中有两个私有的方法readObject和writeObject,这两个方法就是完成集合序列化的秘密武器,下方附上ArrayList序列化部分的源码。

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
            ensureCapacityInternal(size);

            Object[] a = elementData;
            // Read in all elements in the proper order.
            for (int i=0; i<size; i++) {
                a[i] = s.readObject();
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值