關於Java中使用Serializable中readObject和readObject調用的問題


我們都知道,序列化不會自動保存static和transient變量,因此我們若要保存它們,則需要通過writeObject()和readObject()去手動讀寫。
(01) 通過writeObject()方法,寫入要保存的變量。writeObject的原始定義是在ObjectOutputStream.java中,我們按照如下示例覆蓋即可:

private void writeObject(ObjectOutputStream out) throws IOException{ 
    out.defaultWriteObject();// 使定制的writeObject()方法可以利用自動序列化中內置的邏輯。 
    out.writeInt(ival);      // 若要保存“int類型的值”,則使用writeInt()
    out.writeObject(obj);    // 若要保存“Object對象”,則使用writeObject()
}

(02) 通過readObject()方法,讀取之前保存的變量。readObject的原始定義是在ObjectInputStream.java中,我們按照如下示例覆蓋即可:

private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException{ 
    in.defaultReadObject();       // 使定制的readObject()方法可以利用自動序列化中內置的邏輯。 
    int ival = in.readInt();      // 若要讀取“int類型的值”,則使用readInt()
    Object obj = in.readObject(); // 若要讀取“Object對象”,則使用readObject()
}

但是你會很驚奇盡管它們被外部類調用但事實上這是兩個private的方法。並且它們既不存在於java.lang.Object,也沒有在Serializable中聲明。那么ObjectOutputStream如何使用它們的呢?
作為程序員我們有一個終極大殺器,就是看源碼?
以ObjectInputStream 為例:
首先,會調用readObject(),通過Object obj = readObject0(false);調用readObject0;里面有這一句return checkResolve(readOrdinaryObject(unshared));調用
readOrdinaryObject方法 在readOrdinaryObject會調用readSerialData(obj, desc);然后readSerialData會調用slotDesc.invokeReadObject(obj, this);這里調用ObjectStreamClass的invokeReadObject(Object obj, ObjectInputStream in)
里面 readObjectMethod.invoke(obj, new Object[]{ in });這顯然是一個通過發射進行的方法調用,那么readObjectMethod是什么方法?別急繼續往下看,到ObjectStreamClass(final Class<?> cl)
發現里面有這一句readObjectMethod = getPrivateMethod(cl, "readObject",new Class<?>[] { ObjectInputStream.class },Void.TYPE),getPrivateMethod方法如下:

/**
* Returns non-static private method with given signature defined by given
* class, or null if none found. Access checks are disabled on the
* returned method (if any).
*/
private static Method getPrivateMethod(Class<?> cl, String name,
Class<?>[] argTypes,
Class<?> returnType)
{
try {
Method meth = cl.getDeclaredMethod(name, argTypes);
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;
}
}

這下總算搞明白了。

 
         
         
        
 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM