Netty中的泛型

Netty中的泛型用的不是很多,少数几个泛型的目的是为了向用户提供更加友好的接口, 比如启动器类和异步操作类, 而Netty内部的泛型使用很少。

启动器类

Netty只提供了Bootstrap以及ServerBootstrap两个启动器类, 其基类是一个泛型类, 定义如下

public abstract class AbstractBootstrap<
B extends AbstractBootstrap<B, C>,
C extends Channel
> implements Cloneable

乍一看去去这个类的泛型参数定义挺复杂的, 实际上这个类只有一个泛型参数, 那就是C extends Channel, 这个参数表示接收一个Channel的子类作为类型参数.

所以AbstractBootstrap的定义本该是像下面这样简单的

class AbstractBootstrap<C extends Channel>

所以多出来的B extends AbstractBootstrap<B, C>是什么鬼?

实际上这是为了方便最终用户以链式调用的方式使用启动器类的一个实现技巧, B extends AbstractBootstrap<B, C>中的B就是指用户实际使用的启动器类, 这个启动器类是AbstractBootstrap的子类.

举个栗子, 如果不添加这个参数, 以class AbstractBootstrap<C extends Channel>的方式来定义AbstractBootstrap, 那么它的group方法的前面只能是:

public AbstractBootstrap<C> group(EventLoopGroup group)

而用户写下的如下代码便无法编译

ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup).childHandler( ...)

无法编译的原因是AbstractBootstrap并未定义childHandler方法, 是这是子类ServerBootstrap自己定义的方法.而gropu方法返回的是AbstractBootstrap, 自然无法调用子类定义的方法.

而如果在AbstractBootstrap中加上的表示子类自身的泛型参数B extends AbstractBootstrap<B, C>, 那么group方法便可定义成

public B group(EventLoopGroup group)

因为返回值是B, 也就是子类本身, 在上面的例子中返回的是ServerBootstrap, 这样一来, 链式调用childHandler就没有问题了

异步操作类

PromiseaddListener的参数乍一看令人震惊, 下面是addListener的签名以及GenericFutureListener的定义:

Promise<V> addListener(GenericFutureListener<? extends Future<? super V>> listener);

public interface GenericFutureListener<F extends Future<?>> extends EventListener {
void operationComplete(F future) throws Exception;
}

GenericFutureListener并没有什么特别的, 它接收一个Future<?>的子类, 并利用这个类型参数定义了操作完成时的回调方法的签名。

addListenerGenericFutureListener的类型参数<? extends Future<? super V>>是比较有趣的, 它表示接收一个Future<? super V>的子类, 这里详细解释一下这里为何是super, 而不是extends:

因为这里我们需要监听的参数是至少是V, 所以V的父类的监听器可以正常工作, 而V子类的监听器却不能保证能工作。

再举个栗子, 比如我们有个继承链为 food->fruit->apple, 如果需要一个监听器(Listener)来处理fruit, 那么可以传入一个处理food的监听器, 因为fruit一定是food, 但不能传入一个处理apple的监听器, 因为fruit不一定是apple, 也有可能是orange