• 对象序列化


    本文源自:对象序列化为何要定义serialVersionUID的来龙去脉,因为原文不是对“序列化”的完整介绍,所以在此,结合个人理解,将“对象序列化”做一个简要梳理!

    首先,为什么要序列化:

    1. 正常的Web项目中服务过程中,会产生”成百上千“的实例对象,而且随着用户访问量的增加,对象数据量可能会越来越多,例如:session等,那么如果这些对象都保存于服务内存中的话,再大的内存也有可能吃不消,因此,我们就需要将对象序列化到物理磁盘,需要的时候再反序列化回来。
    2. 我们知道对象本身在网络传输过程中是不可能直接传输的,需要进行转换为二进制文件,才能进行正常传送,这个转换过程,我们就称作序列化。

    如何序列化

    1.针对第一种磁盘序列化,我们需要对象实现Serializable接口,将对象以输出流的形式暂存在File文件中,当需要访问它的时候,再通过输入流写回内存。下面看一个示例:

    我们创建一个User对象,只有一个name属性:

    package cn.wxson.serializable;
    
    import lombok.Getter;
    import lombok.Setter;
    
    import java.io.Serializable;
    
    @Setter
    @Getter
    public class User implements Serializable {
    
        private String name;
    
        public User(String name) {
            this.name = name;
        }
    }
    

    我们创建一个User对象outUser,并把它序列化到文件user,再将user文件中的内容反序列化到内存inUser对象中。

    package cn.wxson.serializable;
    
    import lombok.extern.slf4j.Slf4j;
    
    import java.io.*;
    
    @Slf4j
    public class SerializableTest {
    
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            // 将对象序列化到文件
            User outUser = new User("Tom");
            ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream("user"));
            oo.writeObject(outUser);
            oo.close();
    
            // 将文件反序列化为对象
            ObjectInputStream oi = new ObjectInputStream(new FileInputStream("user"));
            User inUser = (User) oi.readObject();
            log.info("Name:" + inUser.getName());
            oi.close();
        }
    }
    

    2.同样的道理,网络传输中的对象序列化,也要实现Serialiable接口,程序内部会自动将对象以字节流形式写入磁盘,然后通过网络通信读取磁盘信息到内存进行传输。当然,写入磁盘的做法是标准IO的做法,那么NIO相较于标准IO传输,能够更快的原因是,它的传输过程不需要对象落地,完全利用系统的虚拟内存技术,从Buffer缓冲区直接将序列化后的对象传输到网络,所以它的传输效率更高。

    serialVersionUID的含义

    我们通常在写代码时,都会为实现Serialiable接口的对象增加serialVersionUID属性。那么,这个serialVersionUID又代表什么含义呢?还是以上一个示例来解释一下!

    我们看到刚才的示例中,User对象并没有serialVersionUID值。那么,我们执行“将对象序列化到user文件”后,在User对象中新增一个age属性:

    package cn.wxson.serializable;
    
    import lombok.Getter;
    import lombok.Setter;
    
    import java.io.Serializable;
    
    @Setter
    @Getter
    public class User implements Serializable {
    
        private String name;
        private int age;
    
        public User(String name) {
            this.name = name;
        }
    }
    

    我们再来执行“将文件反序列化为对象”,这时就会出现以下错误:

    Exception in thread "main" java.io.InvalidClassException: cn.wxson.serializable.User; local class incompatible: stream classdesc serialVersionUID = 4797623867994513725, local class serialVersionUID = -6015633555568763825
    	at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
    	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
    	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
    	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
    	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
    	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
    	at cn.wxson.serializable.SerializableTest.main(SerializableTest.java:19)
    

    那么,为什么会报错呢?

    首先,我们先来看一下报错信息,它的大致意思是,接收对象User中的serialVersionUID与本地文件user中的serialVersionUID不一致导致了该错误。但是,我们没有给User对象和文件user中标识serialVersionUID啊?

    其实,虽然我们没有给User对象指定serialVersionUID属性,但Java编译器对User对象outUser进行序列化时,已经自动给它通过摘要算法(类似于指纹算法)生成了serialVersionUID,存储在user文件中,摘要算法精度很高,这个serialVersionUID值是唯一的,而在我们在为对象新增age属性后,User对象就有了一个新的serialVersionUID值,所以,利用新的serialVersionUID值来反序列化是失败的,接收不到序列化对象。

    正确做法:我们为User对象指定一个固定serialVersionUID值。

    private static final long serialVersionUID = -263618247375550128L;

    同样,重复上面的步骤,先对只有name属性的User对象inUser执行序列化操作,然后,在User中增加age属性后,执行反序列化操作,这次就是成功的了!

    希望通过本文学习,加深你对序列化的理解!

  • 相关阅读:
    Key Figure、Exception Aggreagion、Non-Cumulative KeyFigure
    特征创建:Reference Characteristic、Template
    Compounding绑定属性
    特征的SID表、M表、P表、Q表、X表、Y表、T表
    特征的Attribute Only选项
    将InfoObject作为信息提供者Characteristic is InfoProvider
    滚动RollUp、压缩
    Aggregation 聚集
    VirtualProvider (VirtualCube)虚拟立方体
    自建数据源(RSO2)、及数据源增强
  • 原文地址:https://www.cnblogs.com/ason-wxs/p/13455303.html
Copyright © 2020-2023  润新知