今天在整理博客,看见自己不知道从哪里搬来的博文,虽然自己已经编码三年之久,但还是某些地方会有些许疑惑,稍微总结一些,也方便别
人搬运!
对于序列化的疑惑主要有如下几点?
问题1、为什吗要使用序列化?
问题2、实现序列化的方式?
问题3、对象状态能不能部分实现序列化?
问题4、常见的序列化方式解析
解答(1):
为何要使用序列化?
首先从序列化的概念谈起:序列化是指将对象状态转化为可保持或传输的过程。
计算机最终要的的事情是数据处理,因此我们开发了很多程序、软件去模拟现实世界的数据流转、分析,软件中的各种对象来源于现实生活。
计算机发展的石器时期:是人们将数据录入软件,经过分析后形成一定的结果,结果以文件的形式存储,流转。例如:财务人员将一年公司的支出情况,录入系统,计算机能根据一定的算法统计出财务人员想要的报表数据..等等。
计算机发展的封建时期:由于互联网的发展,人们对于数据的传递速度、传递形式越来越挑剔,这就衍生了数据其他交换形式例如:XML、JSON
String、Byte,数据录入计算机后可以通过Http协议直接将数据传递。
解答(2、3):
序列化的方式及部分序列化:
常见的实现序列化的方式是实现Serializable接口,为什吗实现了此接口对象就可以被序列化呢?
我们看下常用输出流对象:ObjectOutputStream是对Java对象的识别。
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());
} </span>
解答(3):
对象可否部分序列化?
其实这种情况是经常见的,我们的存储的对象某个属性只是一个临时状态或中间值,不是最终数据传输的结果,如果这个字段是以集合或数组的形式存储,那在序列化的时候会非常占用时间,这个时候我们可以考虑用 关键字 transient 声名我们不想被序列化的对象。例如JAVA集合中,ArrayList序列化的使用就恰到好处,有的同学看到源码,不仅要问,数据都存放与暂态数据中,那集合怎嘛被序列化呢?
这就是我们要说的另外一个问题,有时候我们单单声名为暂态是不够的,我们还需要重写对象的序列化过程,
例如ArrayList对象。
1、ArrayList是以数组实现的,数据最终存储的是元素的引用,我们序列化元素的引用是毫无意义的;
2、elementData数组长度是根据数据量的变化动态扩展,那么在最终集合元素构建完成,势必elementData数组的对象会为空,而这些空对象的序列化也是非常占用时间的!
所以jdk 提供了writeObject()方法,我们可以重写序列化方法,达到我们要的目的。如下所示:
可能有些同学还会有疑惑,writeObject 方法在那里调用的,这是个私有方法。
我们点击查看下ObjectOutputStream 的writeSerialData方法,查看源码我们可以发现,他也是根据反射调用的这个方法。
//ArrayList 继承接口Serializable
public classArrayList<E> extends AbstractList<E> implementsList<E>, RandomAccess, Cloneable,java.io.Serializable{
//ArrayList是基于数据实现的,所有的数据都要存储在 elementData 数据中(元素的一个引用)
private transient Object[] elementData;
//序列化过程
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{
int expectedModCount = modCount;
// Write out element count, and any hidden stuff
s.defaultWriteObject();
// Write out array length
s.writeInt(elementData.length);
// Write out all elements in the proper order.
for (int i=0; i<size; i++)
s.writeObject(elementData[i]);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
}