• 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.

  • 相关阅读:
    HTTP与HTTPS
    GL_TEXTURE_SWIZZLE_R GL_TEXTURE_SWIZZLE_G等详解
    分布式事务
    GLSL (4)Uniform
    python制作ppt
    基于OFDM的通信系统模拟实现
    SpringBoot学习之自定义注解(二十五)
    Android修行手册 - 阴影效果的几种实现以及一些特别注意点
    这些提高摸鱼效率的自动化测试技巧,提高打工人幸福感~
    idea设置gradle
  • 原文地址:https://blog.csdn.net/love__guo/article/details/125526886