zoukankan      html  css  js  c++  java
  • 关于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;
    }
    }

    这下总算搞明白了。

    
    
    
    
  • 相关阅读:
    python 将png图片格式转换生成gif动画
    JetBrains系IDE的设置Pycharm PHPStorm
    Nginx 静态页面POST 请求提示405 Not Allowed
    安装SSL证书 and 根域名跳转www域名
    Linux 安装qt5-designer并集成到Pycharm
    Deepin 自动挂载win NTFS磁盘
    Nginx+DNS负载均衡实现
    swoole websocket服务推送
    Linux版 php5.4 升级php7
    百度 Javascript开发 API
  • 原文地址:https://www.cnblogs.com/sharkli/p/5607895.html
Copyright © 2011-2022 走看看