如何解释这个 Java 泛型类型定义?

How to interpret this Java generic type definition?

下面是 netty 4.0.24 框架中的一些代码片段。解释 B 类型参数有点混乱。

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

我认为它基本上是一个具有 2 个参数 B 和 C 的 class。第一个参数 (B) 必须是扩展 class 本身(或子级)和第二个参数 (C) 必须扩展 Channel.

在其中思考有点奇怪,但是您可以拥有一个 class 和 运行 具有相同类型的对象。

排序答案:它的参数是它自己和一个通道。

"B" 似乎代表了 Subclassed AbstractBootstrap 本身。它认为(恕我直言)这是一个奇怪的声明,使子类出现在通用参数中。

请查看 eclipse 中具有子类型层次结构的子类,您可能会发现类似

的内容
class AnyClass extends AbstractBootstrap<AnyClass,AChannel>

所以在这个例子中我们在它的通用声明中重复"AnyClass"

这可能被解释为curiously recurring template pattern的一种形式。

在这种情况下,类型参数B的主要目的是能够在抽象class中引用继承类型。例如,AbstractBootstrap class 有一个方法

B channel(Class<? extends C> channelClass)

所以这里的 return 类型是 第一个类型参数给出的任何类型。查看 AbstractBoottrap class 的已知实现,可以发现

class Bootstrap extends AbstractBootstrap<Bootstrap,Channel>

class ServerBootstrap extends AbstractBootstrap<ServerBootstrap,ServerChannel>

他们收到 "themself" 作为第一个类型参数。所以这些实现的channel方法会return"the type itself".

此处显示了一个可能的使用场景(使用一些虚拟 classes 使其可编译并指出相关部分):

public class BootstrapExample
{
    public static void main(String[] args)
    {
        // On a Bootstrap, calling the 'channel' method
        // will return a Bootstrap 
        Bootstrap bootstrap = new Bootstrap();
        Bootstrap resultBootstrap = 
            bootstrap.channel(null);

        // On a ServerBootstrap, calling the 'channel' method
        // will return a ServerBootstrap 
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        ServerBootstrap resultSeverBootstrap = 
            serverBootstrap.channel(null);
    }
}

abstract class AbstractBootstrap<
    B extends AbstractBootstrap<B, C>, 
    C extends Channel> implements Cloneable
{
    public B channel(Class<? extends C> channelClass)
    {
        return null;
    }
}
class Bootstrap extends AbstractBootstrap<Bootstrap,Channel> {}
class ServerBootstrap 
    extends AbstractBootstrap<ServerBootstrap,ServerChannel> {}
class Channel {}
class ServerChannel extends Channel {}

旁白:我一直提倡类型安全,但是一旦嵌套了这些类型参数,您最终可能会得到 class- 或暗示类型边界的方法声明可以很难手动检查。因此,只有当可读性和类型安全之间的权衡确实合理时,才应使用它们。