3

I am reading through documentation of AgelikaLangerDoc. I have just started reading this article. I have seen the following syntax in the code.

interface Copyable<T>{
  T copy();
}

final class Wrapped<Elem extends Copyable<Elem>>{
}

I am not able to understand the following generics syntax meaning.

<Elem extends Copyable<Elem>>

I know its pretty basic but really generics is tricky. Why do we need to put it like this? We could have said something ike

final class Wrapped<Copyable<Elem>>{
}

I know its not legal but even the above syntax is not easy to understand. Can someone explain this part?

benz
  • 4,561
  • 7
  • 37
  • 68

1 Answers1

4

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:

Bert F
  • 85,407
  • 12
  • 106
  • 123
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • what is the use of doing something like this class CopyableImpl implements Copyable { CopyableImpl copy() { ... } }i am still confused a lil about it. I am really finding deciphering generics pretty tricky. – benz Aug 26 '13 at 13:19
  • 1
    @benz. If you are dealing with some generic type, which works on the type that implements it, then that type would need to be given as type parameter. For example - consider - `Comparable`, if you want a class to be comparable, you would declare it as: `class Test implements Comparable`. – Rohit Jain Aug 26 '13 at 13:34
  • @benz. Well as for deciphering, trust me I was bad at generics few months back. It's only that site - AngelikaLanger's, which made be feel quite confident about it. – Rohit Jain Aug 26 '13 at 13:36
  • Thanks for your valuable time Rohit. I am sure because i am just entering to this field. Finding things pretty tricky. :) hopefully i will be able to benefit from all knowledge you guys have. – benz Aug 26 '13 at 13:37