Hessian源码学习(四)BasicSerializer分析

之前分析了序列化一个对象的流程,基本上可以归纳成先获取一个对象的序列化类,然后由该序列化类来序列化对象;那么究竟有哪些序列化类,以及这些类是如何序列化的就是我们本次分析的重点(参考源码版本3.0.13)!

先看下整个序列化类的的类图:

[img]http://dl.iteye.com/upload/attachment/0072/8729/a44b500e-fa2e-3e5e-93b8-5852b0816c59.jpg[/img]


可以看出:
1.它们都是AbstractSerializer的子类;
2.实现序列化的方法是:void writeObject(Object obj, AbstractHessianOutput out)方法;

现在我们就分别讨论这些类的实现,首先是[b]BasicSerializer[/b]类(用来序列化java基本类型,以及基本类型数组)


Integer obj = new Integer(10);
// 这里得到的就是:BasicSerializer(理由请看上一篇分析)
serializer = _serializerFactory.getSerializer(obj.getClass());
serializer.writeObject(obj, this);

现在我们看下BasicSerializer的writeObject方法:

public void writeObject(Object obj, AbstractHessianOutput out)
throws IOException
{
switch (code) {
// 针对每一种类型,做出相应的序列化
case BOOLEAN:

// 省略后面代码...

default:
throw new RuntimeException(code + " " + String.valueOf(obj.getClass()));
}
}



[size=medium][b]1.现在我们详细的看一下每一种类型如何序列化,首先看下boolean/Boolean[/b][/size]

case BOOLEAN:
out.writeBoolean(((Boolean) obj).booleanValue());
break;

writeBoolean方法的实现还是比较简单的,[b]如果是true就输出'T',否则输出'F'[/b]


public void writeBoolean(boolean value)
throws IOException
{
if (value)
os.write('T');
else
os.write('F');
}

我们看下例子:
out.writeObject(true);

[img]http://dl.iteye.com/upload/attachment/0072/8794/5087c84b-c2a7-36ed-bea0-97763b2e7d3f.jpg[/img]


[size=medium][b]2.序列化 byte, short, int(包括相应的对象类型):[/b][/size]

case BYTE:
case SHORT:
case INTEGER:
out.writeInt(((Number) obj).intValue());
break;

[b]发现没,对于byte, short都是当做int来序列化![/b]

writeInt的输出格式为:[b]‘I’ b32 b24 b16 b8 [/b](b32代表从第32位开始的8位, b24代表从第24位开始的8位,后面以此类推)


public void writeInt(int value)
throws IOException
{
os.write('I');
os.write(value >> 24);
os.write(value >> 16);
os.write(value >> 8);
os.write(value);
}

我们看一个例子:
int intValue = 1234;
out.writeObject(intValue);

[img]http://dl.iteye.com/upload/attachment/0072/8796/01d64de7-0b35-319f-b371-2dd27cbda2fa.jpg[/img]
short shortVale = 300;
out.writeObject(shortVale);

[img]http://dl.iteye.com/upload/attachment/0072/8798/f2f02bf3-a7b4-3801-bc65-8dd8b29c3779.jpg[/img]


[size=medium][b]3.序列化long(包括相应的对象类型)[/b][/size]
case LONG:
out.writeLong(((Number) obj).longValue());
break;

writeLong的输出格式为:[b]'L' b64 b56 b48 b40 b32 b24 b16 b8[/b]

public void writeLong(long value)
throws IOException
{
os.write('L');
os.write((byte) (value >> 56));
os.write((byte) (value >> 48));
os.write((byte) (value >> 40));
os.write((byte) (value >> 32));
os.write((byte) (value >> 24));
os.write((byte) (value >> 16));
os.write((byte) (value >> 8));
os.write((byte) (value));
}



[size=medium][b]4.序列化float, double(包括相应的对象类型)[/b][/size]
case FLOAT:
case DOUBLE:
out.writeDouble(((Number) obj).doubleValue());
break;

从这里我们也可以看出,float也是当做double类型序列化

另外writeDouble的输出格式为:[b]'D' b64 b56 b48 b40 b32 b24 b16 b8[/b]

public void writeDouble(double value)
throws IOException
{
long bits = Double.doubleToLongBits(value);

os.write('D');
os.write((byte) (bits >> 56));
os.write((byte) (bits >> 48));
os.write((byte) (bits >> 40));
os.write((byte) (bits >> 32));
os.write((byte) (bits >> 24));
os.write((byte) (bits >> 16));
os.write((byte) (bits >> 8));
os.write((byte) (bits));
}

我汇总long,double来看一个例子:
long longValue = 1234567L;
double doubleValue = 1.2345D;
out.writeObject(longValue);
out.writeObject(doubleValue);

[img]http://dl.iteye.com/upload/attachment/0072/8804/308a068e-47c8-36c6-bf42-f819cb622a8d.jpg[/img]


[size=medium][b]5.字符char和字符串String的序列化[/b][/size]
case CHARACTER:
out.writeString(String.valueOf(obj));
break;

case STRING:
out.writeString((String) obj);
break;

可以看到char和String都是使用writeString方法进行序列化,序列化格式为:[b]'S' 字符串长度 字符串每个字符的值[/b]

public void writeString(String value)
throws IOException
{
if (value == null) {
os.write('N');
}
else {
int length = value.length();
int offset = 0;

// 这里一段while循环我暂时没有深究,大概是对超长字符串的输出处理
while (length > 0x8000) {
int sublen = 0x8000;

char tail = value.charAt(offset + sublen - 1);

if (0xd800 <= tail && tail <= 0xdbff)
sublen--;

os.write('s');
os.write(sublen >> 8);
os.write(sublen);

printString(value, offset, sublen);

length -= sublen;
offset += sublen;
}

// 输出:'S' 字符串长度
os.write('S');
os.write(length >> 8);
os.write(length);

// 输出:字符串中每个字符的值
printString(value, offset, length);
}
}

我们还是看一个例子比较直观:
String strValue = "Hello Hessian!";
out.writeObject(strValue);

[img]http://dl.iteye.com/upload/attachment/0072/8812/c2fce187-1447-3375-9f1e-c606a1517115.jpg[/img]


[size=medium][b]上面我们基本已经讲了基本类型和相应的对象类型序列化,现在我们来看下相应的数组类型的序列化;[/b][/size]

数组序列化格式比较简单,基本上可以归纳为[b]:'Vt' 长度 '[数组类型' 'l' 数组长度 数组元素... 'z'[/b]
我们仅以long型数组为例:
 case LONG_ARRAY:
{
// 关于这个ref目前可以忽略,后面的文章会说明
if (out.addRef(obj))
return;

long []data = (long []) obj;
// 输出数组格式头:'Vt' 长度5 '[long' 'l' 数组长度
out.writeListBegin(data.length, "[long");
for (int i = 0; i < data.length; i++)
// 输出数组中每一个元素(看看这里是不是很熟悉?对,就是我们刚才分析的那些)
out.writeLong(data[i]);
// 输出结束标记: 'z'
out.writeListEnd();
break;
}

我们具体看下writeListBegin 和 writeListEnd的实现


public boolean writeListBegin(int length, String type)
throws IOException
{
os.write('V');

if (type != null) {
os.write('t');
printLenString(type);
}

if (length >= 0) {
os.write('l');
os.write(length >> 24);
os.write(length >> 16);
os.write(length >> 8);
os.write(length);
}

return true;
}

public void writeListEnd()
throws IOException
{
os.write('z');
}

话不多说,上代码
long[] arrayLong = new long[] { 12345L, 1234L, 789L };
out.writeObject(arrayLong);

[img]http://dl.iteye.com/upload/attachment/0072/8814/19bdcef1-65bc-3046-99ca-911b8096cd4c.jpg[/img]

关于序列化基本类型数组,[b]还有两点需要注意[/b]:

1.序列化short类型数组,虽然type标记是[short,但是其中的每一个元素还是当做int来序列化,同理对于float型数组,标记为[float,但是对于每一个元素时当做double来序列化;

2.byte类型数组的序列化比较特殊,他基本当成了一个String来输出,只是开始标记为'B'


[b][size=medium]总结[/size][/b]

1.BasicSerializer可以序列化哪些类型?(主要是java基本类型,基本类型数组(包括相应的对象类型);

2.对于每一种的序列化格式是什么?

最后我自己制作了一个表格,大致叙说了各个类型的序列化格式:
[img]http://dl.iteye.com/upload/attachment/0072/8817/45f4d0fa-bdea-3ad3-9137-c78a7f67e2cc.jpg[/img]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值