A place holder for a type argument. | |
Generic types have one or more type parameters. Example of a parameterized type: interface Comparable<E> {The identifier E is a type parameter. Each type parameter is replaced by a type argument when an instantiation of the generic type, such as Comparable<Object> or Comparable<? extends Number> , is used. |
|
LINK TO THIS | TypeParameters.FAQ001 |
REFERENCES | How is a generic type defined? What is a bounded type parameter? Where is a type parameter visible (or invisible)? |
A type parameter with one or more bounds. The bounds restrict the set of types that can be used as type arguments and give access to the methods defined by the bounds. | |
When you declare a type parameter T and use it in the implementation of a generic type or method, the type parameter T still denotes an unknown type. The compiler knows that T is a place holder for a type, but it does not know anything about the type. This is okay in some implementations, but insufficient in others. Example (of a generic type without bounds): public class Hashtable<Key,Data> {The implementation of class Hashtable invokes the methods hashCode and equals on the unknown Key type. Since hashCode and equals are methods defined in class Object and available for all reference types, not much need to be known about the unknown Key type. This changes substantially, when we look into the implementation of sorted sequence. Example (of a generic type, so far without bounds): public interface Comparable<T> {The implementation of class TreeMap invokes the method compareTo on the unknown Key type. Since compareTo is not defined for arbitrary types the compiler refuses to invoke the compareTo method on the unknown type Key because it does not know whether the key type has a compareTo method. In order to allow the invocation of the compareTo method we must tell the compiler that the unknown Key type has a compareTo method. We can do so by saying that the Key type implements the Comparable<Key> interface. We can say so by declaring the type parameter Key as a bounded parameter. Example (of the same generic type, this time with bounds): public interface Comparable<T> {In the example above, the type parameter Key has the bound Comparable<Key> . Specification of a bound has two effects:
|
|
LINK TO THIS | TypeParameters.FAQ002 |
REFERENCES | When would I use a wildcard parameterized with a lower bound? What is a type parameter bound? Which types are permitted as type parameter bounds? Can I use different instantiations of a same generic type as bounds of a type parameteer? Does a bound that is a class type give access to all its public members? Can I use a type parameter as part of its own bounds or in the declaration of other type parameters? |
A reference type that is used to further describe a type parameter. It restricts the set of types that can be used as type arguments and gives access to the non-static methods that it defines. | |
A type parameter can be unbounded. In this case any reference type can be used as type argument to replace the unbounded type parameter in an instantiation of a generic type. Alternatively can have one or several bounds. In this case the type argument that replaces the bounded type parameter in an instantiation of a generic type must be a subtype of all bounds. The syntax for specification of type parameter bounds is: <TypeParameter extends Class & Interface 1 & ... & Interface N >A list of bounds consists of one class and/or several interfaces. Example (of type parameters with several bounds): class Pair<A extends Comparable<A> & Cloneable ,This is a generic class with two type arguments A and B , both of which have two bounds. |
|
LINK TO THIS | TypeParameters.FAQ101 |
REFERENCES | What is the difference between a wildcard bound and a type parameter bound? Which types are permitted as type parameter bounds? Can I use different instantiations of a same generic type as bounds of a type parameteer? |
All classes, interfaces and enum types including parameterized types, but no primitive types and no array types. | |
All classes, interfaces, and enum types can be used as type parameter bound, including nested and inner types. Neither primitive types nor array types be used as type parameter bound. Examples (of type parameter bounds): class X0 <T extends int > { ... } // errorThe code sample shows that primitive types such as int and array types such as Object[] are not permitted as type parameter bound. Class types, such as Number or String , and interface types, such as Runnable , are permitted as type parameter bound. Enum types, such as Thread.State are also permitted as type parameter bound. Thread.State is an example of a nested type used as type parameter bound. Non-static inner types are also permitted. Raw types are permitted as type parameter bound; List is an example. Parameterized types are permitted as type parameter bound, including concrete parameterized types such as List<String> , bounded wildcard parameterized types such as List<? extends Number> and Comparable<? super Long> , and unbounded wildcard parameterized types such as Map.Entry<?,?> . A bound that is a wildcard parameterized type allows as type argument all types that belong to the type family that the wildcard denotes. The wildcard parameterized type bound gives only restricted access to fields and methods; the restrictions depend on the kind of wildcard. Example (of wildcard parameterized type as type parameter bound): class X< T extends List<? extends Number> > {Reference variables of type T (the type parameter) are treated like reference variables of a wildcard type (the type parameter bound). In our example the consequence is that the compiler rejects invocation of methods that take an argument of the "unknown" type that the type parameter stands for, such as List.add , because the bound is a wildcard parameterized type with an upper bound. At the same time the bound List<? extends Number> determines the types that can be used as type arguments. The compiler accepts all type arguments that belong to the type family List<? extends Number> , that is, all subtypes of List with a type argument that is a subtype of Number . Note, that even types that do not have subtypes, such as final classes and enum types, can be used as upper bound. In this case there is only one type that can be used as type argument, namely the type parameter bound itself. Basically, the parameterization is pointless then. Example (of nonsensical parameterization): class Box< T extends String > {The compiler rejects all type arguments except String as "not being within bounds". The type parameter T is not needed and the Box class would better be defined as a non-parameterized class. |
|
LINK TO THIS | TypeParameters.FAQ102 |
REFERENCES | What is a type parameter bound? Can I use a type parameter as a type parameter bound? Can I use different instantiations of a same generic type as bounds of a type parameter? Can I use a type parameter as part of its own bounds or in the declaration of other type parameters? How do unbounded wildcard instantiations of a generic type relate to other instantiations of the same generic type? How do wildcard instantiations with an upper bound relate to other instantiations of the same generic type? How do wildcard instantiations with a lower bound relate to other instantiations of the same generic type? Which methods and fields are accessible/inaccessible through a reference variable of a wildcard parameterized type? |
Yes. | |
A type parameter can be used as the bound of another type parameter. Example (of a type parameter used as a type parameter bound): class Triple <T> {In this example the type parameter T of the parameterized class is used as bound of the type parameters U , V and W of a parameterized instance method of that class. Further opportunities for using type parameters as bounds of other type parameters include situations where a nested type is defined inside a generic type or a local class is defined inside a generic method. It is even permitted to use a type parameter as bound of another type parameter in the same type parameter section. |
|
LINK TO THIS | TypeParameters.FAQ102A |
REFERENCES | Can I use a type parameter as part of its own bounds or in the declaration of other type parameters? Which types are permitted as type parameter bounds? Where is a type parameter visible (or invisible)? Can I use different instantiations of a same generic type as bounds of a type parameteer? What is the difference between a wildcard bound and a type parameter bound? |
Can I use different instantiations of a same generic type as bounds of a type parameter?
No, at most one instantiation of the same generic type can appear in the list of bounds of a type parameter. | |
Example (of illegal use of two instantiations of the same generic type as bounds of a type parameter):
class ObjectStore<T extends Comparable<T> & Comparable<String> > { // errorIn the example the type parameter T is required to be Comparable<T> , that is, comparable to its own type. This is needed for storing objects of type T in a TreeSet<T> . At the same time the type parameter T is required to be Comparable<String> , because we want to invoke the type parameter's compareTo(String) method. Remember, type parameter bounds are needed to give the compiler access to the type parameters non-static methods. In this (admittedly contrived) example, we need to specify two instantiations of the Comparable interface as bound of the type parameter, but the compiler rejects it. The reason for this restriction is that there is no type that is a subtype of two different instantiations of the Comparable interface and could serve as a type argument. It is prohibited that a type implements or extends two different instantiations of the same interface. This is because the bridge method generation process cannot handle this situation. Details are discussed in a separate FAQ entry (click here ). If no class can ever implement both instantiations of Comparable , there is no point to a bounds list that requires it. The class in our example would not be instantiable because no type can ever be within bounds, except perhaps class String . In practice, you will need to work around this restriction. Sadly, there might be situations in which there is no workaround at all. |
|
LINK TO THIS | TypeParameters.FAQ103 |
REFERENCES | Can a class implement different instantiations of the same generic interface? What is type erasure? What is a bridge method? How does type erasure work when a type parameter has several bounds? How can work around the restriction that a type parameter cannot have different instantiations of a same generic type as its bounds? |
How can I work around the restriction that a type parameter cannot have different instantiations of a same generic type as its bounds?
Usually there is no satisfactory workaround. | |
Let us use the example from the previous question for our search of a workaround. Example (of illegal use of two instantiations of the same generic type as bounds of a type parameter): class ObjectStore<T extends Comparable<T> & Comparable<String> > { // errorIn the example the type parameter T is required to be Comparable<T> , because objects of type T are stored in a TreeSet<T> . At the same time the type parameter T is required to be Comparable<String> , because we invoke the type parameter's compareTo(String) method. The compiler rejects the attempt of specifying two instantiations of the Comparable interface as bound of the type parameter. One workaround for the example above could be the following: we could drop the requirement that the parameter T must be Comparable<T> , because the corresponding compareTo(T) method is not invoked in the implementation of the generic class itself, but in the operations of the Treeset<T> . By dropping the requirement we would risk that a type argument is supplied that is not Comparable<T> and will cause ClassCastException s when operations of the TreeSet<T> are invoked. Clearly not a desirable solution, but perhaps a viable one for this particular example. However, this might not be a solution if the class uses the type parameter in a slightly different way. For instance, if both compareTo methods were called in the implementation of the generic class, then we could not drop any of the bounds. Example (another class with illegal use of two instantiations of the same generic type as bounds of a type parameter): class SomeClass<T extends Comparable<T> & Comparable<String> > { // errorIf the methods of the bounds are invoked in the class implementation, then dropping one of the conflicting bounds does not solve the problem. One could consider use of an additional interface, such as a CombinedComparable interface that combines the two required interfaces into one interface. Example (conceivable work-around; does not work): interface CombinedComparable<T> {However, this is not really a viable solution, because it excludes class String as a type argument. String is a class that is comparable to itself and to String , but it is does not implement a CombinedComparable interface. Hence type String is not within bounds. Another conceivable alternative is definition of one new interface per instantiation needed, such as a parameterized SelfComparable and a non-parameterized StringComparable interface. Again, this excludes class String as a potential type argument. If it acceptable that class String is excluded as a potential type argument then the definition of additional interfaces might be a viable workaround. But there remain some situations, in which additional interfaces do not help. For instance, if the type parameter is used as type argument of another parameterized method, then it must itself be within the bounds of that other type parameter. Example (another class with illegal use of two instantiations of the same generic type as bounds of a type parameter): class AnUnrelatedClass {No solution sketched out above would address this situation appropriately. If we required that the type parameter be CombinedComparable , it would not be within the bounds of at least one of the two invoked methods. Note, that the CombinedComparable interface can be a subinterface of only one of the two instantiations of Comparable , but not both. Example (conceivable work-around; does not work): interface CombinedComparable<T> extends Comparable<String> {The same happens when we require that the type parameter be SelfComparable and StringComparable . Even if both were subinterfaces of the respective instantiation of Comparable , there cannot be a class that implements both, because that class would indirectly implement the two instantiations of Comparable . Ultimately the realization is that, depending on the circumstances, there might not be a work around at all. |
|
LINK TO THIS | TypeParameters.FAQ104 |
REFERENCES | Can I use different instantiations of a same generic type as bounds of a type parameter? Can a class implement different instantiations of the same parameterized interface? |
Yes, except any constructors. | |
A bound that is a class gives access to all its public members, that is, public fields, methods, and nested type. Only constructors are not made accessible, because there is no guarantee that a subclass of the bound has the same constructors as the bound. Example (of a class used as bound of a type parameter): public class SuperClass {The bound SuperClass gives access to its nested types, static fields and methods and non-static fields and methods. Only the constructor is not accessible. This is because constructors are not inherited. Every subclass defines its own constructors and need not support its superclass's constructors. Hence there is no guarantee that a subclass of SuperClass will have the same constructor as its superclass. Although a superclass bound gives access to types, fields and methods of the type parameter, only the non-static methods are dynamically dispatched. In the unlikely case that a subclass redefines types, fields and static methods of its superclass, these redefinitions would not be accessible through the superclass bound. Example (of a subclass of the bound used for instantiation): public final class SubClass extends SuperClass { // static membersCalling the nonStaticMethod results in invocation of the subclass's overriding version of the nonStaticMethod . In contrast, the subclass's redefinitions of types, fields and static methods are not accessible through the bounded parameter. This is nothing unusual. First, it is poor programming style to redefine in a subclass any of the superclass's nested types, fields and static methods. Only non-static methods are overridden. Second, the kind of hiding that we observe in the example above also happens when a subclass object is used through a superclass reference variable. |
|
LINK TO THIS | TypeParameters.FAQ105 |
REFERENCES |
As a type that can only be instantiation for its subtypes, and those subtypes will inherit some useful methods, some of which take subtype arguments (or otherwise depend on the subtype). | |
The context in which " Enum<E extends Enum<E>> " appears is the declaration of the Enum class in package java.lang :
public abstract class Enum<E extends Enum<E>> {The type Enum is the common base class of all enumeration types. In Java an enumeration type such as Color is translated into a class Color that extends Enum<Color> . The purpose of the superclass Enum is to provide functionality that is common to all enumeration types. Here is a sketch of class Enum : public abstract class Enum< E extends Enum<E>> implements Comparable< E >, Serializable {The surprising feature in the declaration " Enum<E extends Enum<E>> " is the fact that the newly defined class Enum and its newly defined type parameter E appear in the bound of that same type parameter. It means that the Enum type must be instantiated for one of its subtypes. In order to understand why this makes sense, consider that every enum type is translated into a subtype of Enum . Here is the contrived enum type Color : enum Color {RED, BLUE, GREEN}The compiler translates it into the following class: public final class Color extends Enum<Color> {The inheritance has the effect that the Color type inherits all the methods implemented in Enum<Color> . Among them is the compareTo method. The Color.compareTo method should probably take a Color as an argument. In order to make this happen class Enum is generic and the Enum.compareTo method takes Enum 's type parameter E as an argument. As a result, type Color derived from Enum<Color> inherits a compareTo method that takes a Color as and argument, exactly as it should. If we dissect the declaration " Enum<E extends Enum<E>> " we can see that this pattern has several aspects. First, there is the fact that the type parameter bound is the type itself: " Enum <E extends Enum <E>> ". It makes sure that only subtypes of type Enum are permitted as type arguments. (Theoretically, type Enum could be instantiated on itself, like in Enum<Enum> , but this is certainly not intended and it is hard to imagine a situation in which such an instantiation would be useful.) Second, there is the fact that the type parameter bound is the parameterized type Enum <E> , which uses the type parameter E as the type argument of the bound. This declaration makes sure that the inheritance relationship between a subtype and an instantiation of Enum is of the form " X extends Enum<X> ". A subtype such as " X extends Enum<Y> " cannot be declared because the type argument Y would not be within bounds; only subtypes of Enum<X> are within bounds. Third, there is the fact that Enum is generic in the first place. It means that some of the methods of class Enum take an argument or return a value of an unknown type (or otherwise depend on an unknown type). As we already know, this unknown type will later be a subtype X of Enum<X> . Hence, in the parameterized type Enum<X> , these methods involve the subtype X , and they are inherited into the subtype X . The compareTo method is an example of such a method; it is inherited from the superclass into each subclass and has a subclass specific signature in each case. To sum it up, the declaration " Enum<E extends Enum<E>> " can be decyphered as: Enum is a generic type that can only be instantiated for its subtypes, and those subtypes will inherit some useful methods, some of which take subtype specific arguments (or otherwise depend on the subtype). |
|
LINK TO THIS | TypeParameters.FAQ106 |
REFERENCES | How is a generic type defined? What is a bounded type parameter? Where is a type parameter visible (or invisible)? |