之前分析了序列化一个对象的流程,基本上可以归纳成先获取一个对象的序列化类,然后由该序列化类来序列化对象;那么究竟有哪些序列化类,以及这些类是如何序列化的就是我们本次分析的重点(参考源码版本3.0.13)!
先看下整个序列化类的的类图:
可以看出:
1.它们都是AbstractSerializer的子类;
2.实现序列化的方法是:void writeObject(Object obj, AbstractHessianOutput out)方法;
现在我们就分别讨论这些类的实现,首先是
BasicSerializer类(用来序列化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()));
}
}
1.现在我们详细的看一下每一种类型如何序列化,首先看下boolean/Boolean
case BOOLEAN:
out.writeBoolean(((Boolean) obj).booleanValue());
break;
writeBoolean方法的实现还是比较简单的,
如果是true就输出'T',否则输出'F'
public void writeBoolean(boolean value)
throws IOException
{
if (value)
os.write('T');
else
os.write('F');
}
我们看下例子:
out.writeObject(true);
2.序列化 byte, short, int(包括相应的对象类型):
case BYTE:
case SHORT:
case INTEGER:
out.writeInt(((Number) obj).intValue());
break;
发现没,对于byte, short都是当做int来序列化!
writeInt的输出格式为:
‘I’ b32 b24 b16 b8 (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);
short shortVale = 300;
out.writeObject(shortVale);
3.序列化long(包括相应的对象类型)
case LONG:
out.writeLong(((Number) obj).longValue());
break;
writeLong的输出格式为:
'L' b64 b56 b48 b40 b32 b24 b16 b8
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));
}
4.序列化float, double(包括相应的对象类型)
case FLOAT:
case DOUBLE:
out.writeDouble(((Number) obj).doubleValue());
break;
从这里我们也可以看出,float也是当做double类型序列化
另外writeDouble的输出格式为:
'D' b64 b56 b48 b40 b32 b24 b16 b8
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);
5.字符char和字符串String的序列化
case CHARACTER:
out.writeString(String.valueOf(obj));
break;
case STRING:
out.writeString((String) obj);
break;
可以看到char和String都是使用writeString方法进行序列化,序列化格式为:
'S' 字符串长度 字符串每个字符的值
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);
上面我们基本已经讲了基本类型和相应的对象类型序列化,现在我们来看下相应的数组类型的序列化;
数组序列化格式比较简单,基本上可以归纳为
:'Vt' 长度 '[数组类型' 'l' 数组长度 数组元素... 'z'
我们仅以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);
关于序列化基本类型数组,
还有两点需要注意:
1.序列化short类型数组,虽然type标记是[short,但是其中的每一个元素还是当做int来序列化,同理对于float型数组,标记为[float,但是对于每一个元素时当做double来序列化;
2.byte类型数组的序列化比较特殊,他基本当成了一个String来输出,只是开始标记为'B'
总结
1.BasicSerializer可以序列化哪些类型?(主要是java基本类型,基本类型数组(包括相应的对象类型);
2.对于每一种的序列化格式是什么?
最后我自己制作了一个表格,大致叙说了各个类型的序列化格式: