关于jdk1.8容器hashmap中的变量table加了transient修饰后如何序列化。Serializable
2018年03月12日 11:13:24 qq_35516657 阅读数:462
众所周知,transient修饰符的作用是使该变量在序列化的时候不会被储存。
transient Node<K,V>[] table;
但是hashmap中的变量table是储存了容器中所有的元素,在序列化中不被储存,那么反序列化后hashmap对象中岂不是个空容器?
后来通过细想,table里存的只是引用,就算在序列化中储存到硬盘里,反序列化后table变量里的引用已经没有意义了。
至于hashmap是如何在序列化中储存元素呢?原来是它通过重写Serializable接口中的writeObject方法和readObject方法实现的。下面贴出两个方法的源代码。
-
private void writeObject(java.io.ObjectOutputStream s) -
throws IOException { -
int buckets = capacity(); -
// Write out the threshold, loadfactor, and any hidden stuff -
s.defaultWriteObject(); -
s.writeInt(buckets); -
s.writeInt(size); -
internalWriteEntries(s); -
} -
/** -
* 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(); -
reinitialize(); -
if (loadFactor <= 0 || Float.isNaN(loadFactor)) -
throw new InvalidObjectException("Illegal load factor: " + -
loadFactor); -
s.readInt(); // Read and ignore number of buckets -
int mappings = s.readInt(); // Read number of mappings (size) -
if (mappings < 0) -
throw new InvalidObjectException("Illegal mappings count: " + -
mappings); -
else if (mappings > 0) { // (if zero, use defaults) -
// Size the table using given load factor only if within -
// range of 0.25...4.0 -
float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f); -
float fc = (float)mappings / lf + 1.0f; -
int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ? -
DEFAULT_INITIAL_CAPACITY : -
(fc >= MAXIMUM_CAPACITY) ? -
MAXIMUM_CAPACITY : -
tableSizeFor((int)fc)); -
float ft = (float)cap * lf; -
threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ? -
(int)ft : Integer.MAX_VALUE); -
// Check Map.Entry[].class since it's the nearest public type to -
// what we're actually creating. -
SharedSecrets.getJavaOISAccess().checkArray(s, Map.Entry[].class, cap); -
@SuppressWarnings({"rawtypes","unchecked"}) -
Node<K,V>[] tab = (Node<K,V>[])new Node[cap]; -
table = tab; -
// Read the keys and values, and put the mappings in the HashMap -
for (int i = 0; i < mappings; i++) { -
@SuppressWarnings("unchecked") -
K key = (K) s.readObject(); -
@SuppressWarnings("unchecked") -
V value = (V) s.readObject(); -
putVal(hash(key), key, value, false, false); -
} -
} -
}
探讨了JDK 1.8中HashMap如何通过重写Serializable接口的writeObject和readObject方法实现序列化与反序列化,避免使用transient关键字导致的数据丢失问题。
3990

被折叠的 条评论
为什么被折叠?



