An interface definition can be parameterized by using the following syntax:
<interface> -> [<InterfaceModifiers>] interface <idn> ["[" <params> "]"] [<where>] [<ExtendsInterfaces>] <InterfaceBody>
<params> -> <idn> [, <idn>]*
<where> -> where <constraint> [, <constraint>]*
<constraint> -> <idn> [<whereDecl> ";"]*
<whereDecl> -> <methodSig> | <constructorSig>
<methodSig> -> [ static ] <ResultType> <MethodDeclarator> [<Throws>]
<constructorSig> -> <ConstructorDeclarator> [<Throws>]
The params clause lists one or more formal parameter names, each of which stands for a type in the parameterized definition. The where clause lists constraints on the parameters. Each constraint identifies the parameter being constrained; the idn in the constraint must be one of those listed in the params. It then identifies the methods/constructors that that parameter must have. For a method it gives the name, and the types of its arguments and results; it also indicates whether the method is static or not. For a constructor, it lists the types of the arguments. The type names introduced in the params clause can be used as types in the remainder of the interface, including the ExtendsInterfaces clause.