JAVA序列化ID有什么用?

上周一个安卓的兄弟问到了我这个问题,今天我也把这个给写一下分享给大家

JAVA中通常会看到如下代码片断

    import java.io.Serializable; 
    public class A implements Serializable { 
        private static final long serialVersionUID = 1L; 
    }

下面我为序列化提出一些大家通常会疑惑的问题,并做出解答:
什么是序列化类?
序列化类是可以被在网络上传输的(或者也可以被序列化到本地磁盘并生成.ser就文件),并且可以被接收方反序列化

为什么传输的类要被序列化呢?
其实也并不是所有的类都要被序列化,我们看一下JAVA源码

private void writeObject0(Object obj, boolean unshared) throws IOException {
      ...
    if (obj instanceof String) { 
        writeString((String) obj, unshared);
    } else if (cl.isArray()) { 
        writeArray(obj, desc, unshared);
    } else if (obj instanceof Enum) {
        writeEnum((Enum) obj, desc, unshared);
    } else if (obj instanceof Serializable) {
        writeOrdinaryObject(obj, desc, unshared);
    } else {
        if (extendedDebugInfo) {
            throw new NotSerializableException(cl.getName() + "\n"
                    + debugInfoStack.toString());
        } else {
            throw new NotSerializableException(cl.getName());
        }
    }
    ...  }

字符串,数组,枚举这些类型是不需要序列化的,但是除此之外如果不实现Serializable接口就会报NotSerializableException异常

什么是序列化ID呢?
虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致(就是 private static final long serialVersionUID = 1L)
所以反序列化时serialVersionUID也要一致。

什么场景需要序列化?
两个客户端 A 和 B 试图通过网络传递对象数据,A 端将对象 C 序列化为二进制数据再传给 B,B 反序列化得到 C。 若者是序列化到磁盘中,再反序列化到内存。

服务间信息交互用序列化好吗?
我觉得是不好的,并且通常我禁止这样的形为,原因是它提升了服务间的懒依和耦合,理由如下:
1、现在服务间的沟通越来越频繁
2、各服务的团队一般是独立的
3、所以如果用对象序列化的方式,各服务自己的内容变动可能会影响其它服务的正常运行
4、增加了沟通成本和未知性,比如,当我要改变一个DTO时,我得去询问有没有别的服务调用了我,假设我没有所有团队都问到的话就可能会有遗漏,事实上即使我问到了也不一定能得到肯定的答案

更极端一点的,我们甚至规定能走异步通迅的就走异步通讯,这方案几乎被确定为我们的一项开发原则

服务间交互用什么来代替
把一个MAP或对象转为JSON字符串,要什么数据就传什么数据,字符串不需要序列化ID的,内容变动对双方没什么影响,只要不删除依懒方所需要的业务字段就可以。

猜你喜欢

转载自blog.csdn.net/wangqiang9x/article/details/84541316