`
javaroad
  • 浏览: 21034 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

阅读更多

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

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

    }
 

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

 

        List<String> a = new ArrayList<String>();  
        a.add("hello");  
        a.add("world");  
        try {
        	ByteArrayOutputStream st = new ByteArrayOutputStream();  
            ObjectOutputStream out = new ObjectOutputStream(st);  
            out.writeObject(a);  
            byte[] alBytes = st.toByteArray();   
            ArrayList<String> all = null;
			try {
				all = (ArrayList<String>) new ObjectInputStream(
                                           new ByteArrayInputStream(alBytes)).readObject();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}  
            for(String s : all) {
                System.out.println(s);  
            }
        } catch(IOException e) {  
        }  

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

writeObjectMethod.invoke(obj, new Object[]{ out });

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

 

writeObjectMethod = getPrivateMethod(cl, "writeObject", 
			    new Class[] { ObjectOutputStream.class }, 
			    Void.TYPE);

 private static Method getPrivateMethod(Class cl, String name, 
					   Class[] argTypes,
					   Class returnType)
    {
	try {
	    Method meth = cl.getDeclaredMethod(name, argTypes);
            //*****通过反射访问对象的private方法
            meth.setAccessible(true);
	    int mods = meth.getModifiers();
	    return ((meth.getReturnType() == returnType) &&
		    ((mods & Modifier.STATIC) == 0) &&
		    ((mods & Modifier.PRIVATE) != 0)) ? meth : null;
	} catch (NoSuchMethodException ex) {
	    return null;
	}
    }

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

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

 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();
    }
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics