The declaration:
class Wrapped<Elem extends Copyable<Elem>>
simply says that you can only instantiate Wrapped
type with a subtype of Copyable
. Note the Elem
part. It means that the subtype Elem
should be a subtype of Copyable<Elem>
.
For e.g., suppose you have a class that implements that generic interface:
interface Copyable<T>{
T copy();
}
class CopyableImpl implements Copyable<CopyableImpl> {
CopyableImpl copy() { ... }
}
Now you can instantiate the Wrapped
generic type with CopyableImpl
like this:
Wrapped<CopyableImpl>
Replace CopyableImpl
with Elem
and see whether it satisfies the declaration.
CopyableImpl extends Copyable<CopyableImpl>
Elem extends Copyable<Elem>
So, it is a valid type argument for Wrapped
.
However, if your class is something like this:
class SomeCopyable implements Copyable<OtherCopyable> {
OtherCopyable copy() { ... }
}
you cannot instantiate Wrapped
generic type with this class, since it does not satisfy the type parameter for Wrapped
.
SomeCopyable extends Copyable<OtherCopyable>
Elem extends Copyable<Elem2> // Elem 2 is different from Elem
As for your proposal:
class Wrapped<Copyable<Elem>>
no this declaration is completely different from the original one. Considering the fact that generic types are invariant, in the sense, a List<String>
is not a subtype of List<CharSequence>
even though String
is a subclass of CharSequence
. So, for this declaration, you can only instantiate the Wrapped
type with Copyable
type argument like this:
Wrapped<Copyable<String>>
Wrapped<Copyable<Integer>>
Wrapped<CopyableImpl> // Wrong. This doesn't match the type declaration.
Further Reading: