泛型是用来使接口、类、方法更具有通用性,更抽象,
通过 <>尖括号声明泛型,泛型在接口、类、方法上的作用域不一样,跟java中定义的变量的作用域不一样类似,泛型接口和泛型类相似,作用域在整个类上,接口当然就是在整个的实现类上。
泛型接口
//泛型接口 T在接口的实现类中可见
public interface GenericInt2<T> {
public <K> String exec(T t, K k);
}
泛型类
public class GenericClass<T> {
//指定的T的类型在整个类中可见
}
泛型方法
//泛型方法,<K>是声明泛型,K在该方法中可见
public interface GenericInt2<T> {
public <K> String exec(T t, K k);
}
更高级的用法:
<? extends T>:是指上界通配符(Upper Bounds Wildcards)传入的是T的子类
<? super T>:是指下界通配符(Lower Bounds Wildcards)传入的是T的父类
一个小技巧
当一个接口定义为如下形式时:
public interface ICmdHandler<TCmd extends GeneratedMessageV3> {
void handle(ChannelHandlerContext ctx, TCmd cmd);
}
调用是如果message为object时不能直接转换为TCmd泛型类型,需要借助cast函数,因为TCmd是GeneratedMessageV3的子类,object强转为GeneratedMessageV3是不行的,转为子类又不知道要转为哪个子类,所以需要借助cast函数。
ICmdHandler<? extends GeneratedMessageV3> cmdHandler = CmdHandlerFactory.create(msg.getClass());
if (null != cmdHandler) {
cmdHandler.handle(ctx, cast(msg));
}
/**
* 转型消息对象
*
* @param msg
* @param <TCmd>
* @return
*/
static private <TCmd extends GeneratedMessageV3> TCmd cast(Object msg) {
if (null == msg) {
return null;
} else {
return (TCmd) msg;
}
}
泛型的一个使用例子
VO vo = service.getData(requestMsVO, VO::new);
public <T> T getData(RequestMsVO requestMsVO, Supplier<T> targetSupplier){
String data = "{...}"//从requestMsVO中获取的json字符串
//将data转换为VO的类型,这里的VO是getData方法传入的对象
return (T) JSONObject.parseObject(data, targetSupplier.get().getClass());
}