I am taking a course on Generics and it is really good. I am a bit confused on bounded type perameters.
What I am confused about is why you would need to use extends Comparable, because most Classes implement it anyway. I can take any String and do something lik e"abc".compareTo("bcd) and it returns -1. But in a Generic allows to instantiate any class. So here are my questions.
When I extend Comparable on generic in a method like this, does this only allow you to declare or instantiate ONLY objects that already implement Comparable?
If that is true, that would mean that if I extend Comparable on a Generic, it actually LIMITS the classes I can use as the Generic type. Is this correct?
What part is the return type in this "<T extends Comparable<T>> T"?
I believe the T on the right side is the return, but what is it called on the left then?
If my questions do not make sense, just know I am new and rigorously studying and want to learn so that my questions do make sense
If you use a totally unbound generic parameter <T> then the compiler does not have any information about the type that T will have. The only thing the compiler can be certain of is that T will extend Object (since at the time of writing Java does not support primitive generic types). Because of this the compiler will only allow you to call methods that are present in Object.
By adding 'extends Comparable<T>' to the generic type you tell the compiler that as well as being an Object, the type is also a Comparable<T>. This means the compiler is happy to let you compareTo(...) on the object. Without the 'extends' it would be a compiler error to call compareTo.
So yes, using extends in a generic type declaration does restrict the types the generic class can support. This is necessary to allow type safety to be checked when compiling the generic code.
It is a generic interface. It uses a generic type parameter to specify the type of the parameter that is passed to the compareTo(T other) method.
If the type parameter in your class extended Comparable instead of Comparable<T> then the compiler would not be able to be sure of type safety in your code. You might pass in an object that was Comparable<String> and another that was Comparable<Integer>. If you passed a String into the compareTo() method that was expecting an Integer then it would likely break at runtime.
Look up The Curiously Recurring Template Pattern (there's an article on wikipedia). This refers to templates in C++ (which are a little bit similar to genetics in Java, but don't work in quite the same way). That article in Wikipedia also mentions Comparable in Java.
The reason for the <T> after comparable is that comparable is comparable to SOMETHING.
You can have your type any type by saying <T>.
If you want it to be Comparable you can simply say Comparable. But what Comparable isn't simply Comparable, it is Comparable to SOMETHING. If you look it up in the API documentation you find it is called Comparable<T>. So you can have a type which is Comparable to itself, which is how you usually use Comparable. You have an object which implements Comparable, but in the compareTo method you find it uses its own type as a parameter. This is a well‑known exampleSo you would have to call it Comparable<T> but that brings us back where we started, so you have to say that T implements Comparable. You don't use implements in generics, but extends. Yes, generics uses extends both for classes and interfaces. So you now have
T extends Comparable<T>
Remember that for the purposes of extends and super, any type both extends itself and is a supertype of itself, so you can have T which extends T and also is super T. Now, what if you have this sort of code?Now, the Bar class will obviously have a compareTo method but that can be inherited from Foo. So if you are saying that your T means Bar, well Bar hasn't got a compareTo method. And what about a Baz? A Baz should be comparable to a Bar, or to a Foo, or any combination. So you cannot say that the type of a Bar is Bar extends Comparable<Bar>
So when you are writing generic methods, you have to allow for that possibility, so you have to consider that the Comparable bit may refer to a superclass. So you will know it si a superclass of T which means the generics type changes to
T extends Comparable<S super T>
But you don't necessarily know what S is. So you have to pass unknown instead of S, which changes to a question mark, and you get …
[QED ] T extends Comparable<? super T>
And if you're wondering why you need that ? super T, there is a good example: java.sql.Timestamp. This is comparable, but not Comparable<Timestamp> but Comparable<Date> (because Timestamp extends java.util.Date which implements Comparable<Date>). Without the ? super T you wouldn't be ale to use Timestamp as the generic type.