专栏名称: 程序员大咖
为程序员提供最优质的博文、最精彩的讨论、最实用的开发资源;提供最新最全的编程学习资料:PHP、Objective-C、Java、Swift、C/C++函数库、.NET Framework类库、J2SE API等等。并不定期奉送各种福利。
目录
相关文章推荐
程序员的那些事  ·  突发!TP-Link ... ·  20 小时前  
蚂蚁技术AntTech  ·  南京大学与蚂蚁集团成立校级联合实验室,攻坚A ... ·  19 小时前  
京东科技技术说  ·  京东率先开启“3D信息流时代” 让购物更有趣 ·  昨天  
阿里技术  ·  用Cursor开启JAVA+AI生涯 ·  昨天  
51好读  ›  专栏  ›  程序员大咖

深入学习 Java 序列化

程序员大咖  · 公众号  · 程序员  · 2018-05-13 10:24

正文

请到「今天看啥」查看全文



bout.writeShort(STREAM_MAGIC);

bout.writeShort(STREAM_VERSION);

}


在writeStreamHeader()方法中首先会往底层字节容器中写入表示序列化的Magic Number以及版本号,定义为


/**

* Magic number that is written to the stream header.

*/

final static short STREAM_MAGIC = (short)0xaced;

/**

* Version number that is written to the stream header.

*/

final static short STREAM_VERSION = 5;


接下来会调用writeObject()方法进行序列化,实现如下:


public final void writeObject(Object obj) throws IOException {

if (enableOverride) {

writeObjectOverride(obj);

return;

}

try {

// 调用writeObject0()方法序列化

writeObject0(obj, false);

} catch (IOException ex) {

if (depth == 0) {

writeFatalException(ex);

}

throw ex;

}

}


正常情况下会调用writeObject0()进行序列化操作,该方法实现如下:


private void writeObject0(Object obj, boolean unshared)

throws IOException

{

// 一些省略代码

try {

// 一些省略代码

Object orig = obj;

// 获取要序列化的对象的Class对象

Class cl = obj.getClass();

ObjectStreamClass desc;

for (;;) {

Class repCl;

// 创建描述cl的ObjectStreamClass对象

desc = ObjectStreamClass.lookup(cl, true);

// 其他省略代码

}

// 一些省略代码

// 根据实际的类型进行不同的写入操作

// remaining cases

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) {

// 被序列化对象实现了Serializable接口

writeOrdinaryObject(obj, desc, unshared);

} else {

if (extendedDebugInfo) {

throw new NotSerializableException(

cl.getName() + "" + debugInfoStack.toString());

} else {

throw new NotSerializableException(cl.getName());

}

}

} finally {

depth--;

bout.setBlockDataMode(oldMode);

}

}


从代码里面可以看到,程序会


  • 生成一个描述被序列化对象的类的类元信息的ObjectStreamClass对象。

  • 根据传入的需要序列化的对象的实际类型进行不同的序列化操作。从代码里面可以很明显的看到,对于String类型、数组类型和Enum可以直接进行序列化。如果被序列化对象实现了Serializable对象,则会调用writeOrdinaryObject()方法进行序列化。


这里可以解释一个问题:Serializbale接口是个空的接口,并没有定义任何方法,为什么需要序列化的接口只要实现Serializbale接口就能够进行序列化。


答案是:Serializable接口这是一个标识,告诉程序所有实现了”我”的对象都需要进行序列化。


因此,序列化过程接下来会执行到writeOrdinaryObject()这个方法中,该方法实现如下:


private void writeOrdinaryObject(Object obj,

ObjectStreamClass desc,

boolean unshared) throws IOException

{

if (extendedDebugInfo) {

debugInfoStack.push(

(depth == 1 ? "root " : "") + "object (class "" +

obj.getClass().getName() + "", " + obj.toString() + ")");

}

try {

desc.checkSerialize();

bout.writeByte(TC_OBJECT); // 写入Object标志位

writeClassDesc(desc, false); // 写入类元数据

handles.assign(unshared ? null : obj);

if (desc.isExternalizable() && !desc.isProxy()) {

writeExternalData((Externalizable) obj);

} else {

writeSerialData(obj, desc); // 写入被序列化的对象的实例数据

}

} finally {

if (extendedDebugInfo) {

debugInfoStack.pop();

}

}

}


在这个方法中首先会往底层字节容器中写入TC_OBJECT,表示这是一个新的Object


/**

* new Object.

*/

final static byte TC_OBJECT =       (byte)0x73;


接下来会调用writeClassDesc()方法写入被序列化对象的类的类元数据,writeClassDesc()方法实现如下:


private void writeClassDesc(ObjectStreamClass desc, boolean unshared)

throws IOException

{

int handle;

if (desc == null) {

// 如果desc为null

writeNull();

} else if (!unshared && (handle = handles.lookup(desc)) != -1) {

writeHandle(handle);

} else if (desc.isProxy()) {

writeProxyDesc(desc, unshared);

} else {

writeNonProxyDesc(desc, unshared);

}

}


在这个方法中会先判断传入的desc是否为null,如果为null则调用writeNull()方法


private void writeNull() throws IOException {

// TC_NULL =         (byte)0x70;

// 表示对一个Object引用的描述的结束

bout.writeByte(TC_NULL);

}


如果不为null,则一般情况下接下来会调用writeNonProxyDesc()方法,该方法实现如下:


private void writeNonProxyDesc(ObjectStreamClass desc, boolean unshared)

throws IOException







请到「今天看啥」查看全文