开发者社区> 问答> 正文

字节序列反序列化问题

对象的字节序列存在硬盘上,更改了类的属性,反序列化时会造成不兼容问题。“但当serialVersionUID相同时,它就会将不一样的field以type的预设值反序列化,可避开不兼容问题”这句话什么意思?

展开
收起
蛮大人123 2016-03-26 15:10:27 2282 0
1 条回答
写回答
取消 提交回答
  • 我说我不帅他们就打我,还说我虚伪

    简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)。
    可以编写测试类:

    import java.io.Serializable;
    public class Serial implements Serializable {
        private static final long serialVersionUID = 6977402643848374753L;
        int id;
        String name;
    
        public Serial(int id, String name) {
            this.id = id;
            this.name = name;
        }
    
        public String toString() {
            return "DATA: " + id + " " + name;
        }
    
    }

    序列化测试代码:

     import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectOutputStream;
    
    public class SerialTest {
        public static void main(String[] args) {
            Serial serial1 = new Serial(1, "song");
            System.out.println("Object Serial" + serial1);
            try {
                FileOutputStream fos = new FileOutputStream("serialTest.txt");
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                oos.writeObject(serial1);
                oos.flush();
                oos.close();
            } catch (FileNotFoundException e) { // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) { // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    反序列化测试代码:

     import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    
    public class DeserialTest {
        public static void main(String[] args) { // TODO Auto-generated method stub
            Serial serial2;
            try {
                FileInputStream fis = new FileInputStream("serialTest.txt");
                ObjectInputStream ois = new ObjectInputStream(fis);
                serial2 = (Serial) ois.readObject();
                ois.close();
                System.out.println("Object Deserial" + serial2);
            } catch (FileNotFoundException e) { // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) { // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) { // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    可以测试待序列化类Serial设置了版本号,分别运行SerialTest和DeserialTest类后,如果修改Serial类添加一个属性int age,那么再执行DeserialTest的时候还是能够正确运行的。但是如果注释掉版本号后,就会报不兼容异常了,因为我们运行SerialTest序列化时类信息没变更之前的版本号是A,然后修改Serial类的版本号后,并修改了类的属性信息。再执行反序列话时发现读取的字节码信息中的序列号与当前类的版本号不同,所以会任务前后类型版本不一样,有变更,所以报运行时异常了。

    2019-07-17 19:16:17
    赞同 展开评论 打赏
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载