Below is some code snippet from the netty 4.0.24
framework. It's kind of confusing to interpret the B
type parameter.
public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable
{
...
}
“Java Generics are a language feature that allows for definition and use of generic types and methods.” Generic types are instantiated to form parameterized types by providing actual type arguments that replace the formal type parameters. A class like LinkedList<E> is a generic type, that has a type parameter E .
The syntax for a generic method includes a list of type parameters, inside angle brackets, which appears before the method's return type. For static generic methods, the type parameter section must appear before the method's return type.
The declaration of a generic class is almost the same as that of a non-generic class except the class name is followed by a type parameter section. The type parameter section of a generic class can have one or more type parameters separated by commas.
This can possibly be interpreted as one form of the curiously recurring template pattern.
In this case, the main purpose of the type parameter B
is to be able to refer to the inheriting type in the abstract class. For example, the AbstractBootstrap
class has a method
B channel(Class<? extends C> channelClass)
So the return type here is whatever type was given as the first type argument. Looking at the known implementations of the AbstractBoottrap
class, one finds
class Bootstrap extends AbstractBootstrap<Bootstrap,Channel>
and
class ServerBootstrap extends AbstractBootstrap<ServerBootstrap,ServerChannel>
They receive "themself" as the first type parameter. So the channel
method of these implementations will return "the type itself".
A possible usage scenario is shown here (with some dummy classes to make it compileable and point out the relevant part) :
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 {}
An aside: I'm always advocating for type safety, but once these type parameters are nested, you may end up with class- or method declarations that imply type bounds that can hardly be checked manually. So they should only be used when the trade off between readability and type safety is really justified.
I think it is basically a class that have 2 parameters, B and C. The first parameter (B) must be something that extends the class itself (or a child) and the second parameter (C) must extends Channel.
It's a little strange to think in it, but you can have a class that run with objects of it same type.
Sort answer: Its parameters are itself and a channel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With