Hessian 协议解释与实战(五):对象与映射
前段时间,翻译了 Hessian 2.0 的序列化协议,发布在了 Hessian 2.0 序列化协议(中文版)。但是,其中有很多言语不详之处。所以,接下来会用几篇文章来详细解释并实践一下 Hessian 序列化协议,以求做到知其然知其所以然。目录如下:
Hessian 2.0 序列化协议(中文版) — Hessian 序列化协议的中文翻译版。根据后面的“协议解释与实战”系列文章,增加了协议内容错误提示。
Hessian 协议解释与实战(一):布尔、日期、浮点数与整数 — 介绍布尔型数据、日期类型、浮点类型数据和整数类型数据等四种类型的数据的处理。
Hessian 协议解释与实战(二):长整型、二进制数据与 Null — 介绍长整数类型数据、二进制数据和
null
等三种类型的数据的处理。Hessian 协议解释与实战(三):字符串 — 专门介绍了关于字符串的处理。由于字符串需要铺垫的基础知识比较多,处理细节也有繁琐,所以单独成篇来介绍。
Hessian 源码分析(Java) — 开始第四篇分析之前,先来介绍一下 Hessian 的源码实现。方便后续展开说明。
Hessian 协议解释与实战(四):数组与集合 — 铺垫了一些关于实例对象的处理,重点介绍关于数组和集合的相关处理。
Hessian 协议解释与实战(五):对象与映射 — 重点介绍关于对象与映射的相关处理。
Hessian、Msgpack 和 JSON 实例对比 — 用实例对比 JSON、Hessian 和 MessagePack 的区别。
Avro、ProtoBuf、Thrift 的模式演进之路 — 翻译的 Martin Kleppmann 的文章,重点对比了 Avro、ProtoBuf、Thrift 的序列化处理思路。
在上一篇文章 Hessian 协议解释与实战(四):数组与集合 中研究了数组和集合的处理方式。接下来介绍对象和映射的处理。
基础工具方法
基础工具方法就不再赘述,请直接参考 Hessian 协议解释与实战(一):基础工具方法 中提到的几个方法。
另外,在 Hessian 协议解释与实战(四):数组与集合 中,又对一些方法做了扩展和更新。
下面,我们来看一看映射的处理。
映射
坦白讲,个人觉得 Hessian 2.0 序列化协议(中文版):映射 的协议定义写的非常模糊。倒是给的示例,还可圈可点。
相关代码实现
通过 Hessian 源码分析(Java) 可以指定, MapSerializer
是处理映射的 Serializer
。所以,只需要关注一下 MapSerializer
就可以对映射的处理一目了然。结合代码,可以看出,映射的序列化流程大致如下:
AbstractHessianOutput.writeMapBegin(String type)
— 写入映射起始信息;遍历
Map.Entry
,并且是先序列化 Key,然后序列化 Value;AbstractHessianOutput.writeMapEnd()
— 写入映射结束信息。
另外,在 Hessian 源码分析(Java) 中,也提到在 Hessian2Output
中实现了 AbstractHessianOutput
的接口。所以,只需要关注 Hessian2Output
对上述方法的实现即可。
在 Hessian2Output
中可以看出:
Hessian2Output.writeMapBegin(String type)
有两个类型:需要写入类型:
M
,前置标志位后是映射类型信息;不需要写入类型:
H
,这里没有写入类型信息。
AbstractHessianOutput.writeMapEnd()
— 映射结束信息只有一个结束标志位:Z
。这个标志位,在 Hessian 协议解释与实战(四):数组与集合:Collection<Integer>.iterator
👉IteratorSerializer
中也用到了。
下面开始做实验来验证。
HashMap
接下来,我们看一下序列化操作:
/**
* 测试 HashMap 的序列化
*
* @author D瓜哥 · https://www.diguage.com/
*/
@Test
public void testHashMap() throws Throwable {
// 由 MapSerializer 来处理。分三步来处理:
// 1、首先,写入前置标志位 BC_MAP_UNTYPED = 'H'
// 2、其次,遍历 Map.Entry,并将其序列化:①Key ②Value
// 3、最后,写入结束标志位 BC_END = 'Z'
Map<Integer, Car> map = new HashMap<>();
map.put(1, new Car("diguage", 47));
objectTo(map);
}
// -- 输出结果 ------------------------------------------------
== Object: java.util.HashMap ==
== Key Object: java.lang.Integer ==
== Val Object: com.diguage.Car ==
{"1":{"name":"diguage","age":47}}
== byte array: hessian result ==
.... 0 ~ 40 ....
72 0x48 01001000 H
-111 0x91 10010001
67 0x43 01000011 C
15 0x0F 00001111
99 0x63 01100011 c
111 0x6F 01101111 o
109 0x6D 01101101 m
46 0x2E 00101110 .
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
46 0x2E 00101110 .
67 0x43 01000011 C
97 0x61 01100001 a
114 0x72 01110010 r
-110 0x92 10010010
4 0x04 00000100
110 0x6E 01101110 n
97 0x61 01100001 a
109 0x6D 01101101 m
101 0x65 01100101 e
3 0x03 00000011
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
96 0x60 01100000 `
7 0x07 00000111
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
-65 0xBF 10111111
90 0x5A 01011010 Z
从结果上来看,跟我们上面的分析差不多,确定了一些细节:
首先,写入前置标志位
0x48
(H
)其次,遍历
Map.Entry
,并将其序列化Key
Value
最后,写入结束标志位
0x5A
(Z
)。
接下来再看看其他类型的 Map
的处理情况。
TreeMap
来看看 TreeMap
的处理情况:
/**
* 测试 TreeMap 的序列化
*
* @author D瓜哥 · https://www.diguage.com/
*/
@Test
public void testTreeMap() throws Throwable {
Car c = new Car("diguage", 47);
Map<Integer, Car> map = new TreeMap<>();
map.put(1, c);
objectTo(map);
}
// -- 输出结果 ------------------------------------------------
== Object: java.util.TreeMap ==
== Key Object: java.lang.Integer ==
== Val Object: com.diguage.Car ==
{"1":{"name":"diguage","age":47}}
== byte array: hessian result ==
.... 0 ~ 58 ....
77 0x4D 01001101 M
17 0x11 00010001
106 0x6A 01101010 j
97 0x61 01100001 a
118 0x76 01110110 v
97 0x61 01100001 a
46 0x2E 00101110 .
117 0x75 01110101 u
116 0x74 01110100 t
105 0x69 01101001 i
108 0x6C 01101100 l
46 0x2E 00101110 .
84 0x54 01010100 T
114 0x72 01110010 r
101 0x65 01100101 e
101 0x65 01100101 e
77 0x4D 01001101 M
97 0x61 01100001 a
112 0x70 01110000 p
-111 0x91 10010001
67 0x43 01000011 C
15 0x0F 00001111
99 0x63 01100011 c
111 0x6F 01101111 o
109 0x6D 01101101 m
46 0x2E 00101110 .
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
46 0x2E 00101110 .
67 0x43 01000011 C
97 0x61 01100001 a
114 0x72 01110010 r
-110 0x92 10010010
4 0x04 00000100
110 0x6E 01101110 n
97 0x61 01100001 a
109 0x6D 01101101 m
101 0x65 01100101 e
3 0x03 00000011
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
96 0x60 01100000 `
7 0x07 00000111
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
-65 0xBF 10111111
90 0x5A 01011010 Z
针对 TreeMap
的处理,大致也可以分为三步:
首先,写入前置信息:
写入前置标志位
0x4D
(M
)写入
Map
的类型(字符串形式)
其次,遍历
Map.Entry
,并将其序列化Key
Value
最后,写入结束标志位
0x5A
(Z
)。
与 HashMap
不同之处时,这里写入了 Map
的类型信息。所以,相比来说 HashMap
更加轻量级。在做微服务接口的参数和返回结果时,可以优先考虑 HashMap
。
再谈实例对象
为了方便叙述,在 Hessian 协议解释与实战(四):数组与集合:首谈实例对象 中,对对象的处理做了简要的概述。到这里,让我们再来认识一下实例对象。
处理实例对象的序列化主要有
JavaSerializer
和BeanSerializer
。这两者的区别如下:
JavaSerializer
是通过反射获取实例对象的属性进行序列化。排除static
和transient
属性,对其他所有的属性进行递归序列化处理。
BeanSerializer
是遵循 POJI bean 的约定,扫描实例的所有方法,发现同时存在 Getter 和 Setter 方法的属性才进行序列化,它并不直接直接操作所有的属性。注意:BeanSerializer
将会无法处理 Getter 方法是以is
开头的boolean
属性,因为BeanSerializer
只认以get
开头的方法。
在 Java 8 中,其实默认使用的并不是这两个,而是 UnsafeSerializer
。它与 JavaSerializer
相似,都是通过反射获取类的属性列表;但是与 JavaSerializer
不同之处时, JavaSerializer
通过 Field
使用反射获取实例对象属性对应的值;而 UnsafeSerializer
是使用 sun.misc.Unsafe
来获取字段的“指针”(offset
),再通过“指针”获取实例对象属性对应的值。
另外,启用 UnsafeSerializer
的先决条件是能否获得 sun.misc.Unsafe
实例。如果可以获得 sun.misc.Unsafe
实例,则就会启用 UnsafeSerializer
。当然,也可以通过配置 com.caucho.hessian.unsafe
变量为 false
来禁用 UnsafeSerializer
。这里,还有一个例外:如果待序列化的类包含了 writeReplace()
方法,则就会启用 JavaSerializer
。
下面介绍一下继承对象的序列化情况:
继承对象
package com.diguage;
import java.math.BigDecimal;
import java.util.Date;
/**
* 用户
*
* @author D瓜哥 · https://www.diguage.com
*/
public class User {
private Integer id;
private String name;
private Date birthday;
private BigDecimal money;
public User() {
}
public User(Integer id, String name, Date birthday, BigDecimal money) {
this.id = id;
this.name = name;
this.birthday = birthday;
this.money = money;
}
// 各种 Setter 和 Getter 方法
}
package com.diguage;
import java.math.BigDecimal;
import java.util.Date;
/**
* Web用户
*
* @author D瓜哥 · https://www.diguage.com
*/
public class WebUser extends User {
private String site;
public WebUser() {
}
public WebUser(Integer id, String name, Date birthday, BigDecimal money, String site) {
super(id, name, birthday, money);
this.site = site;
}
// 各种 Setter 和 Getter 方法
}
/**
* 测试父子类的序列化
*
* @author D瓜哥 · https://www.diguage.com
*/
@Test
public void testInheritance() throws Throwable {
BigDecimal money = new BigDecimal("1234.56789")
.setScale(2, BigDecimal.ROUND_HALF_UP);
int id = 4;
String name = "diguage";
Date date = new Date();
String site = "https://www.diguage.com";
WebUser webUser = new WebUser(id, name, date, money, site);
objectTo(webUser);
}
// -- 输出结果 ------------------------------------------------
== Object: com.diguage.WebUser ==
== object: json length=107 ==
{
"id": 4,
"name": "diguage",
"birthday": "2022-08-05 19:37:15",
"money": 1234.57,
"site": "https://www.diguage.com"
}
== object: hessian result ==
.... 0 ~ 131 ....
67 0x43 01000011 C
19 0x13 00010011
99 0x63 01100011 c
111 0x6F 01101111 o
109 0x6D 01101101 m
46 0x2E 00101110 .
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
46 0x2E 00101110 .
87 0x57 01010111 W
101 0x65 01100101 e
98 0x62 01100010 b
85 0x55 01010101 U
115 0x73 01110011 s
101 0x65 01100101 e
114 0x72 01110010 r
-107 0x95 10010101
4 0x04 00000100
115 0x73 01110011 s
105 0x69 01101001 i
116 0x74 01110100 t
101 0x65 01100101 e
2 0x02 00000010
105 0x69 01101001 i
100 0x64 01100100 d
4 0x04 00000100
110 0x6E 01101110 n
97 0x61 01100001 a
109 0x6D 01101101 m
101 0x65 01100101 e
8 0x08 00001000
98 0x62 01100010 b
105 0x69 01101001 i
114 0x72 01110010 r
116 0x74 01110100 t
104 0x68 01101000 h
100 0x64 01100100 d
97 0x61 01100001 a
121 0x79 01111001 y
5 0x05 00000101
109 0x6D 01101101 m
111 0x6F 01101111 o
110 0x6E 01101110 n
101 0x65 01100101 e
121 0x79 01111001 y
96 0x60 01100000 `
23 0x17 00010111
104 0x68 01101000 h
116 0x74 01110100 t
116 0x74 01110100 t
112 0x70 01110000 p
115 0x73 01110011 s
58 0x3A 00111010 :
47 0x2F 00101111 /
47 0x2F 00101111 /
119 0x77 01110111 w
119 0x77 01110111 w
119 0x77 01110111 w
46 0x2E 00101110 .
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
46 0x2E 00101110 .
99 0x63 01100011 c
111 0x6F 01101111 o
109 0x6D 01101101 m
-108 0x94 10010100
7 0x07 00000111
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
74 0x4A 01001010 J
0 0x00 00000000
0 0x00 00000000
1 0x01 00000001
-126 0x82 10000010
109 0x6D 01101101 m
-53 0xCB 11001011
-105 0x97 10010111
-9 0xF7 11110111
67 0x43 01000011 C
20 0x14 00010100
106 0x6A 01101010 j
97 0x61 01100001 a
118 0x76 01110110 v
97 0x61 01100001 a
46 0x2E 00101110 .
109 0x6D 01101101 m
97 0x61 01100001 a
116 0x74 01110100 t
104 0x68 01101000 h
46 0x2E 00101110 .
66 0x42 01000010 B
105 0x69 01101001 i
103 0x67 01100111 g
68 0x44 01000100 D
101 0x65 01100101 e
99 0x63 01100011 c
105 0x69 01101001 i
109 0x6D 01101101 m
97 0x61 01100001 a
108 0x6C 01101100 l
-111 0x91 10010001
5 0x05 00000101
118 0x76 01110110 v
97 0x61 01100001 a
108 0x6C 01101100 l
117 0x75 01110101 u
101 0x65 01100101 e
97 0x61 01100001 a
7 0x07 00000111
49 0x31 00110001 1
50 0x32 00110010 2
51 0x33 00110011 3
52 0x34 00110100 4
46 0x2E 00101110 .
53 0x35 00110101 5
55 0x37 00110111 7
从序列化结果上来看,序列化有继承关系的实例对象时,会把对象按照子类一个类处理;但是,和没有继承关系又略有不同:有父子关系的实例对象会先处理子类的属性,然后再处理父类的属性。
重复字符串的处理
在 Hessian 协议解释与实战(四):数组与集合:首谈实例对象 中提到 “重复对象会使用前置标志位 0x51
(Q
)+ 编号来处理”。对于字符串会怎么处理呢?下面做测试来验证一下:
/**
* 测试重复字符串的序列化
*
* @author D瓜哥 · https://www.diguage.com
*/
@Test
public void testDuplicateString() throws Throwable {
String string = "I'm D瓜哥,😁";
List<String> strings = Arrays.asList(string, string);
List<String> stringList = new ArrayList<>(strings);
objectTo(stringList);
}
// -- 输出结果 ------------------------------------------------
== Object: java.util.ArrayList ==
== Generic: java.lang.String ==
== object: json length=27 ==
["I'm D瓜哥,😁","I'm D瓜哥,😁"]
== object: hessian result ==
.... 0 ~ 43 ....
122 0x7A 01111010 z
10 0x0A 00001010
73 0x49 01001001 I
39 0x27 00100111 '
109 0x6D 01101101 m
32 0x20 00100000
68 0x44 01000100 D
-25 0xE7 11100111
-109 0x93 10010011
-100 0x9C 10011100
-27 0xE5 11100101
-109 0x93 10010011
-91 0xA5 10100101
-17 0xEF 11101111
-68 0xBC 10111100
-116 0x8C 10001100
-19 0xED 11101101
-96 0xA0 10100000
-67 0xBD 10111101
-19 0xED 11101101
-72 0xB8 10111000
-127 0x81 10000001
10 0x0A 00001010
73 0x49 01001001 I
39 0x27 00100111 '
109 0x6D 01101101 m
32 0x20 00100000
68 0x44 01000100 D
-25 0xE7 11100111
-109 0x93 10010011
-100 0x9C 10011100
-27 0xE5 11100101
-109 0x93 10010011
-91 0xA5 10100101
-17 0xEF 11101111
-68 0xBC 10111100
-116 0x8C 10001100
-19 0xED 11101101
-96 0xA0 10100000
-67 0xBD 10111101
-19 0xED 11101101
-72 0xB8 10111000
-127 0x81 10000001
从实验结果上来看,对于字符串来说, Hessian 并没有做特殊处理,遇到相同的字符串还是会反复序列化。
“混合”集合的序列化
有小伙伴提了一个问题:如果集合类是有各种各样对象的“混合”集合, Hessian 可以如何序列化的?下面做实验验证一下:
/**
* 测试“混合”集合的序列化
*
* @author D瓜哥 · https://www.diguage.com
*/
@Test
public void testHybridList() throws Throwable {
BigDecimal money = new BigDecimal("1234.56789")
.setScale(2, BigDecimal.ROUND_HALF_UP);
int id = 4;
String name = "diguage";
Date date = new Date();
String site = "https://www.diguage.com";
User user = new User(id, name, date, money);
WebUser webUser = new WebUser(id, name, date, money, site);
Car car = new Car(name, id);
List<Object> hybridList = new ArrayList<>();
// 在集合中,放了 WebUser、 User 和 Car 三个类型的实例对象
hybridList.add(webUser);
hybridList.add(user);
hybridList.add(car);
objectTo(hybridList);
}
// -- 输出结果 ------------------------------------------------
== Object: java.util.ArrayList ==
== Generic: com.diguage.WebUser ==
== object: json length=211(下面是格式化代码) ==
[
{
"id": 4,
"name": "diguage",
"birthday": "2022-08-05 19:57:18",
"money": 1234.57,
"site": "https://www.diguage.com"
},
{
"id": 4,
"name": "diguage",
"birthday": "2022-08-05 19:57:18",
"money": 1234.57
},
{
"name": "diguage",
"age": 4
}
]
== object: hessian result ==
.... 0 ~ 232 ....
123 0x7B 01111011 {
67 0x43 01000011 C
19 0x13 00010011
99 0x63 01100011 c
111 0x6F 01101111 o
109 0x6D 01101101 m
46 0x2E 00101110 .
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
46 0x2E 00101110 .
87 0x57 01010111 W
101 0x65 01100101 e
98 0x62 01100010 b
85 0x55 01010101 U
115 0x73 01110011 s
101 0x65 01100101 e
114 0x72 01110010 r
-107 0x95 10010101
4 0x04 00000100
115 0x73 01110011 s
105 0x69 01101001 i
116 0x74 01110100 t
101 0x65 01100101 e
2 0x02 00000010
105 0x69 01101001 i
100 0x64 01100100 d
4 0x04 00000100
110 0x6E 01101110 n
97 0x61 01100001 a
109 0x6D 01101101 m
101 0x65 01100101 e
8 0x08 00001000
98 0x62 01100010 b
105 0x69 01101001 i
114 0x72 01110010 r
116 0x74 01110100 t
104 0x68 01101000 h
100 0x64 01100100 d
97 0x61 01100001 a
121 0x79 01111001 y
5 0x05 00000101
109 0x6D 01101101 m
111 0x6F 01101111 o
110 0x6E 01101110 n
101 0x65 01100101 e
121 0x79 01111001 y
96 0x60 01100000 `
23 0x17 00010111
104 0x68 01101000 h
116 0x74 01110100 t
116 0x74 01110100 t
112 0x70 01110000 p
115 0x73 01110011 s
58 0x3A 00111010 :
47 0x2F 00101111 /
47 0x2F 00101111 /
119 0x77 01110111 w
119 0x77 01110111 w
119 0x77 01110111 w
46 0x2E 00101110 .
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
46 0x2E 00101110 .
99 0x63 01100011 c
111 0x6F 01101111 o
109 0x6D 01101101 m
-108 0x94 10010100
7 0x07 00000111
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
74 0x4A 01001010 J
0 0x00 00000000
0 0x00 00000000
1 0x01 00000001
-126 0x82 10000010
109 0x6D 01101101 m
-35 0xDD 11011101
-14 0xF2 11110010
21 0x15 00010101
67 0x43 01000011 C
20 0x14 00010100
106 0x6A 01101010 j
97 0x61 01100001 a
118 0x76 01110110 v
97 0x61 01100001 a
46 0x2E 00101110 .
109 0x6D 01101101 m
97 0x61 01100001 a
116 0x74 01110100 t
104 0x68 01101000 h
46 0x2E 00101110 .
66 0x42 01000010 B
105 0x69 01101001 i
103 0x67 01100111 g
68 0x44 01000100 D
101 0x65 01100101 e
99 0x63 01100011 c
105 0x69 01101001 i
109 0x6D 01101101 m
97 0x61 01100001 a
108 0x6C 01101100 l
-111 0x91 10010001
5 0x05 00000101
118 0x76 01110110 v
97 0x61 01100001 a
108 0x6C 01101100 l
117 0x75 01110101 u
101 0x65 01100101 e
97 0x61 01100001 a
7 0x07 00000111
49 0x31 00110001 1
50 0x32 00110010 2
51 0x33 00110011 3
52 0x34 00110100 4
46 0x2E 00101110 .
53 0x35 00110101 5
55 0x37 00110111 7
67 0x43 01000011 C
16 0x10 00010000
99 0x63 01100011 c
111 0x6F 01101111 o
109 0x6D 01101101 m
46 0x2E 00101110 .
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
46 0x2E 00101110 .
85 0x55 01010101 U
115 0x73 01110011 s
101 0x65 01100101 e
114 0x72 01110010 r
-108 0x94 10010100
2 0x02 00000010
105 0x69 01101001 i
100 0x64 01100100 d
4 0x04 00000100
110 0x6E 01101110 n
97 0x61 01100001 a
109 0x6D 01101101 m
101 0x65 01100101 e
8 0x08 00001000
98 0x62 01100010 b
105 0x69 01101001 i
114 0x72 01110010 r
116 0x74 01110100 t
104 0x68 01101000 h
100 0x64 01100100 d
97 0x61 01100001 a
121 0x79 01111001 y
5 0x05 00000101
109 0x6D 01101101 m
111 0x6F 01101111 o
110 0x6E 01101110 n
101 0x65 01100101 e
121 0x79 01111001 y
98 0x62 01100010 b
-108 0x94 10010100
7 0x07 00000111
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
74 0x4A 01001010 J
0 0x00 00000000
0 0x00 00000000
1 0x01 00000001
-126 0x82 10000010
109 0x6D 01101101 m
-35 0xDD 11011101
-14 0xF2 11110010
21 0x15 00010101
81 0x51 01010001 Q
-110 0x92 10010010
67 0x43 01000011 C
15 0x0F 00001111
99 0x63 01100011 c
111 0x6F 01101111 o
109 0x6D 01101101 m
46 0x2E 00101110 .
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
46 0x2E 00101110 .
67 0x43 01000011 C
97 0x61 01100001 a
114 0x72 01110010 r
-110 0x92 10010010
4 0x04 00000100
110 0x6E 01101110 n
97 0x61 01100001 a
109 0x6D 01101101 m
101 0x65 01100101 e
3 0x03 00000011
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
99 0x63 01100011 c
7 0x07 00000111
100 0x64 01100100 d
105 0x69 01101001 i
103 0x67 01100111 g
117 0x75 01110101 u
97 0x61 01100001 a
103 0x67 01100111 g
101 0x65 01100101 e
-108 0x94 10010100
从序列化结果上来看,和 Hessian 协议解释与实战(四):数组与集合:首谈实例对象 介绍的序列化方法是一致的。但是,这种在集合中混合各种各样对象的用法非常容易出问题,建议禁止这样编码!
总结
前面几篇文章介绍了各个前置标志位,这里做一个总结: