• Serializable自定义序列化测试


    Serializable自定义序列化测试

    原始对象:

    class SerializableTest implements Serializable {
        private static final long serialVersionUID = -6950823103822544658L;
        private int age = 0;
        private String name;
    
        public SerializableTest(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "SerializableTest{" +
                    "age=" + age +
                    ", name='" + name + '\'' +
                    '}';
        }
    
        private void writeObject(java.io.ObjectOutputStream out)
                throws IOException {
            System.err.println("writeObject");
            out.defaultWriteObject();
        }
    
        Object writeReplace() throws ObjectStreamException {
            System.err.println("writeReplace");
            return new SerializableTest(1, "zhangsan");
        }
    
        private void readObject(java.io.ObjectInputStream in)
                throws IOException, ClassNotFoundException {
            System.err.println("readObject");
            in.defaultReadObject();
        }
    
        Object readResolve() throws ObjectStreamException {
            System.err.println("readResolve");
            return new SerializableTest(2, "lisi");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    测试代码:

    SerializableTest serializableTest = new SerializableTest(0, "");
    String fileName = "text.txt";
    try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(fileName));
         ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(fileName));){
        outputStream.writeObject(serializableTest);
        outputStream.flush();
        // --------------
        SerializableTest deSerializableTest = (SerializableTest) inputStream.readObject();
        System.err.println(deSerializableTest);
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    执行结果:

    writeReplacewriteObjectreadObjectreadResolve执行结果
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L1lnvatb-1656496426977)(C:\Users\SunAiguo\AppData\Roaming\Typora\typora-user-images\image-20220629170009501.png)]
    ×[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CHJjX7o0-1656496426979)(C:\Users\SunAiguo\AppData\Roaming\Typora\typora-user-images\image-20220629170101434.png)]
    ×[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cJ4hTzpj-1656496426980)(C:\Users\SunAiguo\AppData\Roaming\Typora\typora-user-images\image-20220629170141441.png)]
    ××[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-96kEASrG-1656496426981)(C:\Users\SunAiguo\AppData\Roaming\Typora\typora-user-images\image-20220629170227578.png)]
    ×××[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oR8P03iF-1656496426982)(C:\Users\SunAiguo\AppData\Roaming\Typora\typora-user-images\image-20220629170436809.png)]
    ×××[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NElQET7S-1656496426982)(C:\Users\SunAiguo\AppData\Roaming\Typora\typora-user-images\image-20220629170502793.png)]

    根据执行结果可以看出:

    • 执行顺序:writeReplace -> writeObject -> readObject -> readResolve
    • writeReplace方法会覆盖原始数据
    • readResolve会覆盖原始数据

    readObjectNoData

    新增父类,并添加readObjectNoData()方法

    class BaseTest implements Serializable {
        private static final long serialVersionUID = -1L;
        private Integer sex;
    
        @Override
        public String toString() {
            return "BaseTest{" +
                    "sex=" + sex +
                    '}';
        }
    
        private void readObjectNoData()
                throws ObjectStreamException {
            System.err.println("readObjectNoData");
        }
    }
    class SerializableTest extends BaseTest implements Serializable {
        ....
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    测试代码,移除输出流代码:

    String fileName = "text.txt";
    try (ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(fileName));){
        // --------------
        SerializableTest deSerializableTest = (SerializableTest) inputStream.readObject();
        System.err.println(deSerializableTest);
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    执行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B3wsidOq-1656496426983)(C:\Users\SunAiguo\AppData\Roaming\Typora\typora-user-images\image-20220629173801991.png)]

    测试发现是新增父类、父类变更时才会调用当前方法,当前类加readObjectNoData()方法没有被调用。(已测试未附图)

    For serializable objects, the readObjectNoData method allows a class to control the initialization of its own fields in the event that a subclass instance is deserialized and the serialization stream does not list the class in question as a superclass of the deserialized object. This may occur in cases where the receiving party uses a different version of the deserialized instance’s class than the sending party, and the receiver’s version extends classes that are not extended by the sender’s version. This may also occur if the serialization stream has been tampered; hence, readObjectNoData is useful for initializing deserialized objects properly despite a “hostile” or incomplete source stream.

    private void readObjectNoData() throws ObjectStreamException;
    Each serializable class may define its own readObjectNoData method. If a serializable class does not define a readObjectNoData method, then in the circumstances listed above the fields of the class will be initialized to their default values (as listed in section 4.5.5 of The JavaTM Language Specification, Second Edition); this behavior is consistent with that of ObjectInputStream prior to version 1.4 of the JavaTM 2 SDK, Standard Edition, when support for readObjectNoData methods was introduced. If a serializable class does define a readObjectNoData method and the aforementioned conditions arise, then readObjectNoData will be invoked at the point during deserialization when a class-defined readObject method would otherwise be called had the class in question been listed by the stream as a superclass of the instance being deserialized.

  • 相关阅读:
    java毕业设计财务信息管理mybatis+源码+调试部署+系统+数据库+lw
    终于有人将jvm讲清楚了,阿里架构师推荐jvm架构解析
    怎么把视频转换成音频
    [SpringBoot系列]缓存解决方案
    初识C++ (二)
    通过STM32Cube配置完成基于I2C协议的AHT20温湿度传感器的数据采集
    【经验分享】基于Linux命令行编程环境的栈追溯和反汇编技术实践分享
    剩余内存无法满足申请时,系统会怎么做?
    原汁多功能榨汁机触摸芯片-DLT8T02S-杰力科创
    获得1688商品详情 API 返回值说明
  • 原文地址:https://blog.csdn.net/love__guo/article/details/125526886