ArrayList序列化与反序列化:
public static void main(String[] args) throws IOException, ClassNotFoundException {
   List<String> stringList = new ArrayList<String>();
    stringList.add("1");
    stringList.add("2");
    stringList.add("3");
    stringList.add("4");
    System.out.println("init StringList" + stringList);
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("stringlist"));
    objectOutputStream.writeObject(stringList); IOUtils.close(objectOutputStream);
    File file = new File("stringlist");
    ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
    List<String> newStringList = (List<String>)objectInputStream.readObject();
    IOUtils.close(objectInputStream);
    if(file.exists()){
      file.delete();
    }
    System.out.println("new StringList" + newStringList);
}
#输出
#init StringList[1, 2, 3, 4]
#new StringList[1, 2, 3, 4]

如上示例所示,ArrayList能正常序列化与反序列化,通过如下源码可以看出
elementData是transient修饰,
通过该属性的声明方式我们知道,他是无法通过序列化持久化下来的。
transient Object[] elementData; // non-private to simplify nested class access
---ArrayList源码中这样定义

那么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();
}
}
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();
}
}
}
通过源码发现ArrayList定义了两个方法readObject与writeObject,众所周知:
  1. 在序列化过程中,如果被序列化的类中定义了writeObject 和 readObject 方法,虚拟机会试图调用对象类里的 writeObject 和 readObject 方法,进行用户自定义的序列化和反序列化。
  2. 如果没有这样的方法,则默认调用是 ObjectOutputStream 的 defaultWriteObject 方法以及 ObjectInputStream 的 defaultReadObject 方法。
  3. 用户自定义的 writeObject 和 readObject 方法可以允许用户控制序列化的过程,比如可以在序列化的过程中动态改变序列化的数值。

那么为什么ArrayList要用这种方式来实现序列化呢?

ArrayList实际上是动态数组,每次在放满以后自动增长设定的长度值,如果数组自动增长长度设为100,而实际只放了一个元素,那就会序列化99个null元素。

为了保证在序列化的时候不会将这么多null同时进行序列化,ArrayList把元素数组设置为transient。