ActiveJ学习心得——serializer(2)

2021SC@SDUSC

一、代码分析内容

本次博客介绍BinarySerializers、CompatibilityLevel、CorruptedDataException、SerializerBuilder、StringFormat这五个单独的类和serializer模块的util工具包。通过这几个类和util包中的类,我们可以对上一次博客中介绍的几个类有更好的理解。

二、util包结构


util工具包中的类还是比较少的,只有BinaryOutputUtils,RecordSerializer和Utils这三个类。作用也是比较容易理解。

三、代码解读

我们可以先来看一下util包中的类。
1.BinaryOutputUtils类
BinaryOutputUtils类提供将原语和字符串写入字节数组的方法,从这个类的类名就能看出来,这个类是为BinaryOutput提供工具方法的。这个类都是各种write方法,在上一个博客分析BinaryOutput类的时候,我们能看到它就是导入了BinaryOutputUtils类,里面的每一个write方法都是return的BinaryOutputUtils类中的方法。我们可以来看一下。
下面是write的几个方法,第一个write调用第二个write,第二个write方法是调用System.arraycopy(bytes, bytesOff, buf, off, len);这条系统方法。

	public static int write(byte[] buf, int off, byte[] bytes) {
    
    
		return write(buf, off, bytes, 0, bytes.length);
	}

	public static int write(byte[] buf, int off, byte[] bytes, int bytesOff, int len) {
    
    
		System.arraycopy(bytes, bytesOff, buf, off, len);
		return off + len;
	}

再来看下一个write方法,writeBoolean方法,它也是调用的writeByte方法的。

	public static int writeBoolean(byte[] buf, int off, boolean v) {
    
    
		return writeByte(buf, off, v ? (byte) 1 : 0);
	}

	public static int writeByte(byte[] buf, int off, byte v) {
    
    
		buf[off] = v;
		return off + 1;
	}

后面还有许多都是一对一对的,例如writeShort和writeShortLE方法,区别就是加了LE。通过代码可以发现,它们的不同就是v的取值范围不同。它们的范围应该是互补的。

public static int writeShort(byte[] buf, int off, short v) {
    
    
		buf[off] = (byte) (v >>> 8);
		buf[off + 1] = (byte) v;
		return off + 2;
	}

	public static int writeShortLE(byte[] buf, int off, short v) {
    
    
		buf[off] = (byte) v;
		buf[off + 1] = (byte) (v >>> 8);
		return off + 2;
	}

其他剩下的方法也都是write各种格式的字符,格式都差不多,理解其中一对,对其他方法也能比较好的理解下去。
2.RecordSerializer类
RecordSerializer类的属性和构造方法如下,RecordSerializer类的其中一个属性是BinarySerializer对象,BinarySerializer类表示将值编码和解码为字节数组的序列化程序。

	private final RecordScheme scheme;
	private final BinarySerializer<?>[] fieldSerializers;

	private RecordSerializer(RecordScheme scheme) {
    
    
		this.scheme = scheme;
		this.fieldSerializers = new BinarySerializer[scheme.size()];
	}

这个类中也是为了做编码和解码的。
encode方法调用了serializer的encode方法,将BinaryOutput对象out编码记录为recode对象。
decode方法调用了serializer的decode方法,将BinaryInput的输入in解码成系统可以使用的格式,然后记录为record。

	@Override
	public void encode(BinaryOutput out, Record record) {
    
    
		for (int i = 0; i < fieldSerializers.length; i++) {
    
    
			//noinspection unchecked
			BinarySerializer<Object> serializer = (BinarySerializer<Object>) fieldSerializers[i];
			serializer.encode(out, record.get(i));
		}
	}

	@Override
	public Record decode(BinaryInput in) throws CorruptedDataException {
    
    
		Record record = scheme.record();
		for (int i = 0; i < fieldSerializers.length; i++) {
    
    
			BinarySerializer<?> serializer = fieldSerializers[i];
			record.set(i, serializer.decode(in));
		}
		return record;
	}

3.Utils类
这个类虽然名字为Utils,看起来好像有很多工具的样子,实际上里面只有一个get方法,返回的是supplier.get():

	public static <T> T get(Supplier<T> supplier) {
    
    
		return supplier.get();
	}

介绍完了util包中的几个类,下面接着介绍那几个单独的类
4.BinarySerializers类
这个类里面有各种各样的编码和解码方法,并且不同的编码、解码方法是通过定义不同对象实现的,我们可以看一下下面这个例子:

	public static final BinarySerializer<Byte> BYTE_SERIALIZER = new BinarySerializer<Byte>() {
    
    
		@Override
		public int encode(byte[] array, int pos, Byte item) {
    
    
			return BinaryOutputUtils.writeByte(array, pos, item);
		}

		@Override
		public Byte decode(byte[] array, int pos) {
    
    
			return array[pos];
		}

		@Override
		public void encode(BinaryOutput out, Byte item) throws ArrayIndexOutOfBoundsException {
    
    
			out.writeByte(item);
		}

		@Override
		public Byte decode(BinaryInput in) {
    
    
			return in.readByte();
		}
	};

从上面的例子可以看出,这个是BinarySerializer类定义的一个BYTE_SERIALIZER 对象,从字面意义上来看就是字节序列化,也就是说这个对象里面的encode和decode都是和byte字节相关的。我们可以从encode中看到,它调用了BinaryOutputUtils.writeByte方法,这就可以印证上面的猜想了。其他的对象也都与这个对象类似,对象名带有哪个格式名,encode和decode就与哪个结构相关。
5.CompatibilityLevel类
这个类的作用就是定义相容性水平。下面是它的属性、构造函数和两个方法:

	private final int level;
	private final boolean littleEndian;

	CompatibilityLevel(int level, boolean littleEndian) {
    
    
		this.level = level;
		this.littleEndian = littleEndian;
	}

	public int getLevel() {
    
    
		return level;
	}

	public boolean isLittleEndian() {
    
    
		return littleEndian;
	}

等级最低是1,最高是4,我们可以来看一下每一个等级都代表什么。
LEVEL1:提供序列化程序的基本版本,@Deprecated LEVEL_1(1, false),
LEVEL2:为ISO8859-1和UTF8提供字符串优化,@Deprecated LEVEL_2(2, false),
LEVEL3:包括以前的优化,并为枚举、子类、数组、映射和列表提供可为空的优化,@Deprecated LEVEL_3(3, false),
LEVEL3_LE:与LEVEL_3相同,但为JVM内部函数提供了很少的endian格式,@Deprecated LEVEL_3_LE(3, true),
LEVEL4:包括以前的优化,并为boolean,LEVEL_4(4, false),
LEVEL4_LE:与LEVEL_4相同,但为JVM内部函数提供很少的endian格式,LEVEL_4_LE(4, true);

四、总结

本次博客介绍了util包中三个类,和另外两个单独的类。我认为,其中BinaryOutputUtils类是比较重要的,因为其他的类要定义encode方法时,总是要用到BinaryOutputUtils类中的对应的方法。

猜你喜欢

转载自blog.csdn.net/zth_idea/article/details/121493636