本帖最后由 ainibc 于 2014-11-27 21:45:06 编辑

解决方案 »

  1.   

    我没看源码,不过猜测一下的话,大概有两种情况:第一,你确定 s.defaultWriteObject();写了ArrayList的size?如果是,那么就是第二种情况,s.defaultWriteObject()还写了其他的很多属性,这帮我们节省了很多工作,所以尽管多写一个size,那还是利大于弊。
      

  2.   

    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.
      

  3.   

    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….
    解释的很清楚了。
      

  4.   

    你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();
        }
      

  5.   

    我怎么觉得我jdk的代码都是错的,  数据读到Object[] a = elementData 里面,并没有赋值给ArrayList 的成员变量elementData呀.
      

  6.   

    错了, a = elementData 是赋值了
      

  7.   

    看了眼源码,源代码写的没问题。
    他writeObject首先执行默认输出,由于数组不在序列化内容里,所以他把内部数组的长度先输出出去,然后再输出每个数组元素。
    readObject时首先读取默认对象,然后读取数组长度(int),初始化内部数组,根据size初始化数组中的元素。
    注意:elementData.length和size并不相等。
      

  8.   

    s.defaultWriteObject();        // Write out array length
            s.writeInt(elementData.length);
    其中private transient Object[] elementData;
      

  9.   

    这个是线程同步的么,读取后当前线程是立即看到了结果么?JVM 中对这种可见性是如何解释的?