Hessian源码学习(四)BasicSerializer分析

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

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

Hessian源码学习(四)BasicSerializer分析_第1张图片


可以看出:
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);

Hessian源码学习(四)BasicSerializer分析_第2张图片
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);

Hessian源码学习(四)BasicSerializer分析_第3张图片

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

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

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


总结

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

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

最后我自己制作了一个表格,大致叙说了各个类型的序列化格式:
Hessian源码学习(四)BasicSerializer分析_第4张图片

你可能感兴趣的:(Serialize)