ArrayList源码分析——如何实现Serializable

来源:互联网 发布:日本三菱材料数据造假 编辑:程序博客网 时间:2024/06/04 18:51

出处:http://java-road-126-com.iteye.com/blog/1463313

  首先,序列化的实现方式:实现Serializable;如果提供了writeObject方法,就会在序列化的时候执行这个方法。看看ArrayList有是如何实现这个方法的。从如下源码中,很容易看到的一点是循环时i<size而不是i<elementData.length,看出端倪了吧,原来,序列化时,我们完全没有必要序列化elementData的所有值。

Java代码  收藏代码
  1. private void writeObject(java.io.ObjectOutputStream s)  
  2.         throws java.io.IOException{  
  3.     // Write out element count, and any hidden stuff  
  4.     int expectedModCount = modCount;  
  5.     s.defaultWriteObject();  
  6.   
  7.         // Write out array length  
  8.         s.writeInt(elementData.length);  
  9.   
  10.     // Write out all elements in the proper order.  
  11.     for (int i=0; i<size; i++)  
  12.             s.writeObject(elementData[i]);  
  13.   
  14.     if (modCount != expectedModCount) {  
  15.             throw new ConcurrentModificationException();  
  16.         }  
  17.   
  18.     }  
 

   看这段源码又引出另外一个问题既然该方法是private的,那到底序列化的时候会不会派上用场呢?解决疑问的最好方式是实践,debug。如下是测试源码:

 

Java代码  收藏代码
  1.      List<String> a = new ArrayList<String>();    
  2.      a.add("hello");    
  3.      a.add("world");    
  4.      try {  
  5.         ByteArrayOutputStream st = new ByteArrayOutputStream();    
  6.          ObjectOutputStream out = new ObjectOutputStream(st);    
  7.          out.writeObject(a);    
  8.          byte[] alBytes = st.toByteArray();     
  9.          ArrayList<String> all = null;  
  10. try {  
  11.     all = (ArrayList<String>) new ObjectInputStream(  
  12.                                         new ByteArrayInputStream(alBytes)).readObject();  
  13. catch (ClassNotFoundException e) {  
  14.     e.printStackTrace();  
  15. }    
  16.          for(String s : all) {  
  17.              System.out.println(s);    
  18.          }  
  19.      } catch(IOException e) {    
  20.      }    

    接下来,我们再看看ObjectOutputStream的writeObject又做了哪些事情。它会根据传进来的ArrayList对象得到Class,然后再包装成ObjectStreamClass,在writeSerialData方法里,会调用ObjectStreamClass的invokeWriteObject方法,最重要的代码如下:

Java代码  收藏代码
  1. writeObjectMethod.invoke(obj, new Object[]{ out });  

    实例变量writeObjectMethod的赋值方式如下:

 

Java代码  收藏代码
  1. writeObjectMethod = getPrivateMethod(cl, "writeObject",   
  2.                 new Class[] { ObjectOutputStream.class },   
  3.                 Void.TYPE);  
  4.   
  5.  private static Method getPrivateMethod(Class cl, String name,   
  6.                        Class[] argTypes,  
  7.                        Class returnType)  
  8.     {  
  9.     try {  
  10.         Method meth = cl.getDeclaredMethod(name, argTypes);  
  11.             //*****通过反射访问对象的private方法  
  12.             meth.setAccessible(true);  
  13.         int mods = meth.getModifiers();  
  14.         return ((meth.getReturnType() == returnType) &&  
  15.             ((mods & Modifier.STATIC) == 0) &&  
  16.             ((mods & Modifier.PRIVATE) != 0)) ? meth : null;  
  17.     } catch (NoSuchMethodException ex) {  
  18.         return null;  
  19.     }  
  20.     }  

    到此为止,我们已经很清楚的掌握ArrayList的序列化过程。再看看HashMap等其他容器类,序列化的实现都如出一辙。

   反序列化的过程是调用readObject方法,有了writeObject介绍,这个方法就不用介绍了吧,你懂的!

Java代码  收藏代码
  1. private void readObject(java.io.ObjectInputStream s)  
  2.        throws java.io.IOException, ClassNotFoundException {  
  3. // Read in size, and any hidden stuff  
  4. s.defaultReadObject();  
  5.   
  6.        // Read in array length and allocate array  
  7.        int arrayLength = s.readInt();  
  8.        Object[] a = elementData = new Object[arrayLength];  
  9.   
  10. // Read in all elements in the proper order.  
  11. for (int i=0; i<size; i++)  
  12.            a[i] = s.readObject();  
  13.    } 

0 0
原创粉丝点击