接上篇:https://developer.aliyun.com/article/1228147?spm=a2c6h.13148508.setting.28.21084f0eNCKPti
八、 使用泛型屏蔽类型的差异性
在C++语言中,有个很好用的模板(template)功能,可以编写带有参数化类型的通用版本,让编译器自动生成针对不同类型的具体版本。而在Java语言中,也有一个类似的功能叫泛型(generic)。在编写类和方法的时候,一般使用的是具体的类型,而用泛型可以使类型参数化,这样就可以编写更通用的代码。
许多人都认为,C++模板(template)和Java泛型(generic)两个概念是等价的,其实实现机制是完全不同的。C++模板是一套宏指令集,编译器会针对每一种类型创建一份模板代码副本;Java泛型的实现基于”类型擦除”概念,本质上是一种进行类型限制的语法糖。
1. 泛型类
以支撑类为例,定义泛型的通用支撑类:
2. 泛型接口
定义泛型的数据提供者接口:
3. 泛型方法
定义泛型的浅拷贝函数:
4. 泛型通配符
泛型通配符一般是使用“?”代替具体的类型实参,可以把“?”看成所有类型的父类。当具体类型不确定的时候,可以使用泛型通配符“?”;当不需要使用类型的具体功能,只使用Object类中的功能时,可以使用泛型通配符“?”。
在Java规范中,不建议使用泛型通配符“?”,上面函数可以改为:
5. 泛型上下界
在使用泛型的时候,我们还可以为传入的泛型类型实参进行上下界的限制,如:类型实参只准传入某种类型的父类或某种类型的子类。泛型上下界的声明,必须与泛型的声明放在一起。
1) 上界通配符(extends)
上界通配符为”extends”,可以接受其指定类型或其子类作为泛参。其还有一种特殊的形式,可以指定其不仅要是指定类型的子类,而且还要实现某些接口。例如:List表明这是A某个具体子类的List,保存的对象必须是A或A的子类。对于List列表,不能添加A或A的子类对象,只能获取A的对象。
2) 下界通配符(super)
下界通配符为”super”,可以接受其指定类型或其父类作为泛参。例如:List表明这是A某个具体父类的List,保存的对象必须是A或A的超类。对于List列表,能够添加A或A的子类对象,但只能获取Object的对象。
PECS(Producer Extends Consumer Super)原则
• 作为生产者提供数据(往外读取)时,适合用上界通配符(extends);
• 作为消费者消费数据(往里写入)时,适合用下界通配符(super)。
在日常编码中,比较常用的是上界通配符(extends),用于限定泛型类型的父类。例子代码如下:
后记
笔者曾在通信行业从业十余年,接入了各类网管和设备的北向接口协议上百余种,涉及到传输、交换、接入、电源、环境等专业,接触了CORBA、HTTP/HTTPS、WebService、Socket TCP/UDP、串口RS232/485等接口,总结出一套接口协议封装的”方法论”。其中,把接口协议文档中的数据格式转化为Java的枚举、结构体、联合体等数据结构,是接口协议封装中极其重要的一步。