为什么 'java.util.HashMap' 中的成员字段 'table' 是临时的?

Why member field 'table' in 'java.util.HashMap' is transient?

我了解到,transient 关键字可防止在序列化对象时保留使用 transient 关键字声明的实例字段的

下面是来自java.util.HashMap的代码:

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {

             ....
             static class Node<K,V> implements Map.Entry<K,V> {...}
             transient Node<K,V>[] table;
}

为什么实例字段 table 的值不是序列化的一部分?因为从实现的角度来看,table 字段的值是 class HashMap 实例的实际内容。

注意:here 是一个使用 transient 关键字的练习。

一个HashMap的实例有两个影响其性能的参数:初始容量和加载因子。容量是哈希 table 中的桶数,初始容量只是创建哈希 [​​=18=] 时的容量。

由于在您提到的示例中 'table' 是使用其他 2 个参数构建的,并由该数据结构用于表示,因此无需担心其序列化。

例如你可以在下面看到它:

   public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);

        // Find a power of 2 >= initialCapacity
        int capacity = 1;
        while (capacity < initialCapacity)
            capacity <<= 1;

        this.loadFactor = loadFactor;
        threshold = (int)(capacity * loadFactor);
        table = new Entry[capacity];
        init();
    }

How does one decide to not serialize a member by giving transient modifier?

  1. 当字段引用的资源没有序列化意义时。例如,OutputStream 或 Window 句柄。
  2. 当字段可以从序列化的其他信息中重建时。这有助于减少需要写入的数据量。

For example, why member field table is not part of serialization?

因为(2)。看看 HashMap class 中的 readObject 方法。 table 字段是使用 class.

中的其他信息重建的

因为Node<K, V>[] table是稀疏的,把这个数组全部序列化很浪费时间。相反,我们只需要序列化数组中的非空元素就足以在以后重建table。

    void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
        Node<K,V>[] tab;
        if (size > 0 && (tab = table) != null) {
            for (int i = 0; i < tab.length; ++i) {
                for (Node<K,V> e = tab[i]; e != null; e = e.next) {
                    s.writeObject(e.key);
                    s.writeObject(e.value);
                }
            }
        }
    }