defaultWriteObject()作用是把非静态字段和非瞬时字段写入流,所以size已经由该方法写入,我不太明白多写一次size有何利处? Open Declaration void java.io.ObjectOutputStream.defaultWriteObject() throws IOException Write the non-static and non-transient fields of the current class to this stream. This may only be called from the writeObject method of the class being serialized. It will throw the NotActiveException if it is called otherwise.
defaultReadObject() and defaultWriteObject() should be the first method call inside readObject(ObjectInputStream o) and writeObject(ObjectOutputStream o). It reads and writes all the non transient fields of the class respectively. These methods also helps in backward and future compatibility. If in future you add some non-transient field to the class and you are trying to deserialize it by the older version of class then the defaultReadObject() method will neglect the newly added field, similarly if you deserialize the old serialized object by the new version then the new non transient field will take default value from JVM i.e. if its object then null else if primitive then boolean to false, int to 0 etc…. 解释的很清楚了。
你jdk是什么版本? 我的是s.writeInt(elementData.length); jdk 1.7.0_21 读的时候也不一样,, /** * 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 array length s.writeInt(elementData.length); // 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 { // Read in size, and any hidden stuff s.defaultReadObject(); // Read in array length and allocate array int arrayLength = s.readInt(); Object[] a = elementData = new Object[arrayLength]; // Read in all elements in the proper order. for (int i=0; i<size; i++) a[i] = s.readObject(); }
我怎么觉得我jdk的代码都是错的, 数据读到Object[] a = elementData 里面,并没有赋值给ArrayList 的成员变量elementData呀.
Open Declaration void java.io.ObjectOutputStream.defaultWriteObject() throws IOException
Write the non-static and non-transient fields of the current class to this stream. This may only be called from the writeObject method of the class being serialized. It will throw the NotActiveException if it is called otherwise.
解释的很清楚了。
读的时候也不一样,,
/**
* 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 array length
s.writeInt(elementData.length); // 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 {
// Read in size, and any hidden stuff
s.defaultReadObject(); // Read in array length and allocate array
int arrayLength = s.readInt();
Object[] a = elementData = new Object[arrayLength]; // Read in all elements in the proper order.
for (int i=0; i<size; i++)
a[i] = s.readObject();
}
他writeObject首先执行默认输出,由于数组不在序列化内容里,所以他把内部数组的长度先输出出去,然后再输出每个数组元素。
readObject时首先读取默认对象,然后读取数组长度(int),初始化内部数组,根据size初始化数组中的元素。
注意:elementData.length和size并不相等。
s.writeInt(elementData.length);
其中private transient Object[] elementData;