上周一个安卓的兄弟问到了我这个问题,今天我也把这个给写一下分享给大家
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的,内容变动对双方没什么影响,只要不删除依懒方所需要的业务字段就可以。