In Java, the Collections class contains the following method:
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> c)
Its signature is well-known for its advanced use of generics,
so much that it is mentioned in the Java in a Nutshell book
and in the official Sun Generics Tutorial.
However, I could not find a convincing answer to the following question:
Why is the formal parameter of type Collection<? extends T>, rather
than Collection<T>? What's the added benefit?
Type inference is a tricky topic that I'll admit that I don't know that much about. However, examine this example:
public class ScratchPad {
private static class A implements Comparable<A> {
public int compareTo(A o) { return 0; }
}
private static class B extends A {}
private static class C extends B {}
public static void main(String[] args)
{
Collection<C> coll = null;
B b = Scratchpad.<B>min(coll);
}
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> c) {
return null;
}
//public static <T extends Object & Comparable<? super T>> T min(Collection<T> c) {
// return null;
//}
}
Consider that the first signature of min() allows the call to compile whereas the second does not. This isn't a very practical example, since one must ask why I would be explicitly typing the method to <B>, but perhaps there is an implicit inference where B would be the inferred type.
One benefit of the ? is that it prohibits additions of items to the Collection
I think it actually doesn't give you anything more for this method, however its a good habit to get into when T is part of the class and not just a static method.
They are including it here so it can become the new convention where every generic should be extended by ?
A class of T should follow PECS: What is PECS (Producer Extends Consumer Super)?
But a static method doesn't need to (at least the parameters, the return value should always)
This is to support a legacy signature of the method in Java 1.4 ( and before ).
Prior to Java 5 the signature for these methods was
public static Object min ( Collection c );
With multiple bounds the erasure rules make the first bound the raw type of the method, so without Object & the signature would be
public static Comparable min ( Collection c );
and legacy code would break.
This is taken from O'Reilly's Java Generics and Collections book, chapter 3.6
Building on the comments I put on Mark's answer, if you have something like
class Play {
class A implements Comparable<A> {
#Override
public int compareTo(A o) {
return 0;
}
}
class B extends A {
}
class C extends A {
}
public static <T extends Object & Comparable<? super T>> T min(
Collection<? extends T> c) {
Iterator<? extends T> i = c.iterator();
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) < 0)
candidate = next;
}
return candidate;
}
public static List<? extends A> getMixedList() {
Play p = new Play();
ArrayList<A> c = new ArrayList<A>();
c.add(p.new C());
c.add(p.new B());
return c;
}
public static void main(String[] args) {
ArrayList<A> c = new ArrayList<A>();
Collection<? extends A> coll = getMixedList();
A a = Play.min(coll);
}
}
It's clearer that min returns an object of type A (the actual signature is <A> A Play.min(Collection<? extends A> c) ). If you leave min(Collection<T>) without the extends part then Play.min(coll) will have the following signature <? extends A> ? extends A Play.min(Collection<? extends A> c) which isn't as clear.
Related
I've read awesome "Effective Java" by Joshua Bloch. But one example in the books is left unclear to me. It's taken from chapter about generics, exact item is "Item 28: Use bounded wildcards to increase API flexibility".
In this item it's shown how to write the most universal and bulletproof (at the type system point of view) version of the algorithm of selection maximum element from collection using bounded type parameters and bounded wildcard types.
The final signature of the static method written looks like this:
public static <T extends Comparable<? super T>> T max(List<? extends T> list)
And it's mostly the same as the one of Collections#max function from standard library.
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
I understand why we need bounded wildcard in T extends Comparable<? super T> type constraint, but is it really necessary in type of the argument? It seems to me that it will be the same if we leave just List<T> or Collection<T>, isn't it? I mean something like this:
public static <T extends Comparable<? super T>> T wrongMin(Collection<T> xs)
I've written the following silly example of using both signatures and don't see any diferrence:
public class Algorithms {
public static class ColoredPoint extends Point {
public final Color color;
public ColoredPoint(int x, int y, Color color) {
super(x, y);
this.color = color;
}
#Override
public String toString() {
return String.format("ColoredPoint(x=%d, y=%d, color=%s)", x, y, color);
}
}
public static class Point implements Comparable<Point> {
public final int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public String toString() {
return String.format("Point(x=%d, y=%d)", x, y);
}
#Override
public int compareTo(Point p) {
return x != p.x ? x - p.x : y - p.y;
}
}
public static <T extends Comparable<? super T>> T min(Collection<? extends T> xs) {
Iterator<? extends T> iter = xs.iterator();
if (!iter.hasNext()) {
throw new IllegalArgumentException("Collection is empty");
}
T minElem = iter.next();
while (iter.hasNext()) {
T elem = iter.next();
if (elem.compareTo(minElem) < 0) {
minElem = elem;
}
}
return minElem;
}
public static <T extends Comparable<? super T>> T wrongMin(Collection<T> xs) {
return min(xs);
}
public static void main(String[] args) {
List<ColoredPoint> points = Arrays.asList(
new ColoredPoint(1, 2, Color.BLACK),
new ColoredPoint(0, 2, Color.BLUE),
new ColoredPoint(0, -1, Color.RED)
);
Point p1 = wrongMin(points);
Point p2 = min(points);
System.out.println("Minimum element is " + p1);
}
So can you suggest an example where such simplified signature will be inacceptable?
P.S. And why the heck there is T extends Object in official implementation?
Answer
Well, thanks to #Bohemian I've managed to figure out what's the difference between them.
Consider the following two auxiliary methods
private static void expectsPointOrColoredPoint(Point p) {
System.out.println("Overloaded for Point");
}
private static void expectsPointOrColoredPoint(ColoredPoint p) {
System.out.println("Overloaded for ColoredPoint");
}
Sure, it's not very smart to overload method both for superclass and its subclass, but it let us see what type of return value was actually inferred (points is List<ColoredPoint> as before).
expectsPointOrColoredPoint(min(points)); // print "Overloaded for ColoredPoint"
expectsPointOrColoredPoint(wrongMin(points)); // print "Overloaded for ColoredPoint"
For both methods inferred type was ColoredPoint.
Sometimes you want be explicit about type passed to overloaded function. You may do it a couple of ways:
You can cast:
expectsPointOrColoredPoint((Point) min(points)); // print "Overloaded for Point"
expectsPointOrColoredPoint((Point) wrongMin(points)); // print "Overloaded for Point"
Still no difference...
Or you can tell compiler what type should be inferred using syntax class.<type>method:
expectsPointOrColoredPoint(Algorithms.<Point>min(points)); // print "Overloaded for Point"
expectsPointOrColoredPoint(Algorithms.<Point>wrongMin(points)); // will not compile
Aha! Here is the answer. List<ColoredPoint> can't be passed to function expecting Collection<Point> because generics are not covariant (unlike arrays), but can be passed to function expecting Collection<? extends Point>.
I'm not sure where or who may prefer to use explicit type parameter in such case, but at least it shows where the wrongMin may be inappropriate.
And thanks to #erickson and #tom-hawtin-tackline for answers about purpose of T extends Object constraint.
The difference is in the type returned, especially influenced by inference, whereby the type may be a type hierarchically between the Comparable type and the List type. Let me give an example:
class Top {
}
class Middle extends Top implements Comparable<Top> {
#Override
public int compareTo(Top o) {
//
}
}
class Bottom extends Middle {
}
Using the signature you've provided:
public static <T extends Comparable<? super T>> T max(List<? extends T> list)
we can code this without errors, warnings or (importantly) casts:
List<Bottom> list;
Middle max = max(list); // T inferred to be Middle
And if you need a Middle result, without inference, you can explicitly type the call to Middle:
Comparable<Top> max = MyClass.<Middle>max(list); // No cast
or to pass to a method that accepts Middle (where inference won't work)
someGenericMethodThatExpectsGenericBoundedToMiddle(MyClass.<Middle>max(list));
I don't know if this helps, but to illustrate the types the compiler as allowed/inferred, the signature would look like this (not that this compiles, of course):
public static <Middle extends Comparable<Top>> Middle max(List<Bottom> list)
The difference between
T max(Collection<? extends T> coll)
and
T wrongMax(Collection<T> xs)
is that the return type of the second version is exactly the same as the collection's element type T, while in the first version T can be a super type of the element type.
The second question: the reason for T extends Object makes sure that T is a class and not an interface.
Update: A slightly more "natural" demonstration of the difference: Suppose you define these two methods:
static void happy(ColoredPoint p, Point q) {}
static void happy(Point p, ColoredPoint q) {}
And call the first one them like this:
happy(coloredPoint, min(points));
happy(coloredPoint, wrongMin(points));
The type inference engine could be able to deduce that in the first call the return type of min should be Point and the code would compile. The second call would fail to compile since the call to happy is ambiguous.
Unfortunately the type inference engine isn't powerful enough at least in Java 7, so in reality both calls fail to compile. The difference is that the first call can be fixed by specifying the type parameter as in Algorithms.<Point>min, while fixing the second call would require an explicit cast.
Not an easy one, but i'll try to be as specific as possible:
in T max(Collection<? extends T> coll)
you could pass an argument like this List<Animal> or List<Cat> or List<Dog>,
and in T wrongMax(Collection<T> xs)
where T is Animal you can't pass as an Argument this
List<Dog>, List<Cat> of course in Runtime you could add Cat or Dog objects in List<Animal> but in compilation time you wouldn't be able to pass a subclass of Animal in the Type of the List being passed as an argument in the wrongMax method, in the other hand, in the max method you could. Sorry for my english, i still learning it :), Regards.
I have a couple of questions about generic wildcards in Java:
What is the difference between List<? extends T> and List<? super T>?
What is a bounded wildcard and what is an unbounded wildcard?
In your first question, <? extends T> and <? super T> are examples of bounded wildcards. An unbounded wildcard looks like <?>, and basically means <? extends Object>. It loosely means the generic can be any type. A bounded wildcard (<? extends T> or <? super T>) places a restriction on the type by saying that it either has to extend a specific type (<? extends T> is known as an upper bound), or has to be an ancestor of a specific type (<? super T> is known as a lower bound).
The Java Tutorials have some pretty good explanations of generics in the articles Wildcards and More Fun with Wildcards.
If you have a class hierarchy A, B is a subclass of A, and C and D are both subclasses of B like below
class A {}
class B extends A {}
class C extends B {}
class D extends B {}
Then
List<? extends A> la;
la = new ArrayList<B>();
la = new ArrayList<C>();
la = new ArrayList<D>();
List<? super B> lb;
lb = new ArrayList<A>(); //fine
lb = new ArrayList<C>(); //will not compile
public void someMethod(List<? extends B> lb) {
B b = lb.get(0); // is fine
lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B
}
public void otherMethod(List<? super B> lb) {
B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List<A> and only contain instances of A
lb.add(new B()); // is fine, as we know that it will be a super type of A
}
A bounded wildcard is like ? extends B where B is some type. That is, the type is unknown but a "bound" can be placed on it. In this case, it is bounded by some class, which is a subclass of B.
Josh Bloch also has a good explanation of when to use super and extends in this google io video talk where he mentions the Producer extends Consumer super mnemonic.
From the presentation slides:
Suppose you want to add bulk methods to Stack<E>
void pushAll(Collection<? extends E> src);
– src is an E producer
void popAll(Collection<? super E> dst);
– dst is an E consumer
There may be times when you'll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.
Collection<? extends MyObject>
means that it can accept all object who have IS- A relationship with MyObject (i.e. any object which is a type of myObject or we can say any object of any subclass of MyObject) or a object of MyObject class.
For example:
class MyObject {}
class YourObject extends MyObject{}
class OurObject extends MyObject{}
Then,
Collection<? extends MyObject> myObject;
will accept only MyObject or children of MyObject(i.e. any object of type OurObject or YourObject or MyObject, but not any object of superclass of MyObject).
In general,
If a structure contains elements with a type of the form ? extends E, we can get elements out of the structure, but we cannot put
elements into the structure
List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<? extends Number> nums = ints;
nums.add(3.14); // compile-time error
assert ints.toString().equals("[1, 2, 3.14]");
To put elements into the structure we need another kind of wildcard called Wildcards with super,
List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
List<Integer> ints = Arrays.asList(5, 6);
Collections.copy(objs, ints);
assert objs.toString().equals("[5, 6, four]");
public static <T> void copy(List<? super T> dst, List<? extends T> src) {
for (int i = 0; i < src.size(); i++) {
dst.set(i, src.get(i));
}
}
Generic wildcards are created to make methods that operate on Collection more reusable.
For example, if a method has a parameter List<A>, we can only give List<A> to this method. It is a waste for this method's funtion under some circumstances:
If this method only reads objects from List<A>, then we should be allowed to give List<A-sub> to this method. (Because A-sub IS a A)
If this method only inserts objects to List<A>, then we should be allowed to give List<A-super> to this method. (Because A IS a A-super)
learn by example:
consider the sort() method in Collections class which use both extends and super:
public static <T extends Comparable<? super T>> void sort(List<T> list){...}
so
why <T extends Comparable<...>>: becuase we need list items (T) to be a subclass of the Comparable interface.
why Comparable<? super T>: becuase we allow the Comparable type
to be a Comparable of any super type of T.
Consider
interface Comparable<T>{
public int compareTo(T o);
}
public static <T extends Comparable<? super T>> void sort(List<T> list){...}
public static <T extends Comparable<T>> void sort2(List<T> list){...}
class A implements Comparable<A>{
#Override
public int compareTo(A o) {
...
}
}
class B extends A {
}
List<A> listA = new ArrayList<>();
List<B> listB = new ArrayList<>();
sort(listA); //ok
sort(listB); //ok
sort2(listA); //ok
sort2(listB); //Error
I was reading an article on Java Generics when I stumbled on this method signature:
static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll);
The part that I don't get is why we need to have
Collection<? extends T> coll
wouldn't
Collection<T> coll
do as well?
Could someone please explain why the following signature is not adequate?
static <T extends Object & Comparable<? super T>> T max(Collection<T> coll);
Thanks in advance for your replies. This keeps puzzling me for quite some time now..
Gábor is correct. The wildcard allows the static type of the returned object to differ from the declared parameter type of the collection you input. For example, given these classes:
interface S extends Comparable<S> {}
class A implements S {
#Override
public int compareTo(final #NotNull S o) {
return 0;
}
}
class B implements S {
#Override
public int compareTo(final #NotNull S o) {
return 0;
}
}
And this class:
class Test {
#Nullable
static <T extends Comparable<? super T>> T extendsMax(
Collection<? extends T> coll) {
return null;
}
#Nullable
static <T extends Comparable<? super T>> T max(Collection<T> coll) {
return null;
}
}
Observe what calls compile and what calls do not:
public static void main(String[] args) {
final Collection<S> sColl = new ArrayList<>();
final Collection<A> aColl = new ArrayList<>();
final Collection<B> bColl = new ArrayList<>();
final S s1 = Test.<S> extendsMax(sColl); // compiles, T = S, <? extends T> = S
final S s2 = Test.<S> extendsMax(aColl); // compiles, T = S, <? extends T> = A
final S s3 = Test.<S> extendsMax(bColl); // compiles, T = S, <? extends T> = B
final A a1 = Test.<A> extendsMax(aColl); // compiles, T = A
final B b1 = Test.<B> extendsMax(bColl); // compiles, T = B
final S s4 = Test.<S> max(sColl); // compiles, T = S
final S s5 = Test.<S> max(aColl); // does not compile, T = S, T != A
final S s6 = Test.<S> max(bColl); // does not compile, T = S, T != B
final S s7 = Test.max(aColl); // compiles, but because T = A, and A
// can be assigned to S
}
So the wildcard allows for some flexibility. While you can omit the wildcard (and to be honest, I can't think of a place off the top of my head where the wildcard is required), there is a reason it is there.
Tom is also incorrect. You can add null to collections with a wildcard (if the collection supports add() in the first place):
List<? extends Number> list = new ArrayList<>();
list.add(null); // compiles, and should execute just fine
And because add(), remove(), and most other mutators in the Collection interface are optional operations, it wouldn't be safe to mutate the collection anyways through those methods if the parameter is just declared as a Collection. In addition, it's generally possible to use iterator().remove() or something of the sort to remove elements from collections regardless of whether they were declared with a wildcard, especially for the ones already included in the Java Collections Framework.
So while a wildcard does limit what you can do with a collection, it should not be used as a way to prevent changes to a collection.
While I was trying to solve exercise from generics tutorial Q&A My answers were slightly different
My Answers
public static <T extends Comparable<? super T>>
T max(List<? extends T> list, int begin, int end) //Option1
public static <T extends Comparable<T>>
T max(List<? extends T> list, int begin, int end) //Option2
from quoted answer below
So My question is
Option1 :Would it make any difference if T extends Object & Comparable<? super T> is replaced with T extends Comparable<? super T>. Isn't extends Object implicit ?
Option2 :Would it make any difference if Comparable<? super T> is replaced with Comparable<T> ? if so How ?
Eclipse code completion creates local variable List<? extends Comparable<? super Comparable<? super T>>> list; on Ctrl+1 max(list, 1, 10); which is bit lengthy. How to Define a classes (hierarchy) that extends Comparable<? super T> , create list and add instances to the list and invoke below method ? Basically I want to know how to invoke max() after adding class instances A or B into a list where class B extends A
Write a generic method to find the maximal element in the range
[begin, end) of a list.
Answer:
import java.util.*;
public final class Algorithm {
public static <T extends Object & Comparable<? super T>>
T max(List<? extends T> list, int begin, int end) {
T maxElem = list.get(begin);
for (++begin; begin < end; ++begin)
if (maxElem.compareTo(list.get(begin)) < 0)
maxElem = list.get(begin);
return maxElem;
}
}
Would it make any difference if Comparable<? super T> is replaced with Comparable<T> ? if so How ?
Remember that Comparables are always consumers, i.e., a Comparable<T> consumes T instances, so it should always be preferrable to use Comparable<? super T> instead of Comparable<T> (Quoting - PECS). It would make difference in case you are comparing a type whose super class implements a Comparable<SuperType>. Consider the following code:
class Parent implements Comparable<Parent> {
protected String name;
#Override
public int compareTo(Parent o) {
return this.name.compareTo(o.name);
}
}
class Child extends Parent {
public Child(String name) {
this.name = name;
}
}
Now if you give your type parameter as T extends Comparable<T>, you won't be able to call that method for List<Child>, as Child does not implement Comparable<Child> but Comparable<Parent>:
public static <T extends Comparable<T>> T max(List<? extends T> list, int begin, int end) {
...
}
public static void main(String[] args) {
List<Child> list = new ArrayList<Child>();
max(list, 0, 2); // Error with current method. Child does not implement Comparable<Child>
}
Hence the type parameter bounds should be T extends Comparable<? super T>.
Note that, you can't change your Child class to:
class Child extends Parent implements Comparable<Child>
because in that case, Child class would extend from different instantiation of same generic type, which is not allowed.
Would it make any difference if T extends Object & Comparable<? super T> is replaced with T extends Comparable<? super T>. Isn't extends Object implicit ?
Well, there is a difference between the two bounds. In the 1st bound, the erasure of the type parameter is Object, whereas in the 2nd bound, the erasure is Comparable.
So, without Object bound, your code will compile to:
public static Comparable max(List list, int begin, int end)
The issue might come when you are generifying the legacy non-generic code. It's neccessary to give Object also as upper bound to avoid breaking the Byte Code compatibility. You can read more about it on this link: Angelika Langer - Programming Idioms
It looks like there are more wildcards than necessary. I'll probably go with
public static <T extends Comparable<? super T>>
T max(List<T> list, int begin, int end)
An even more constrained version:
public static <T extends C, C extends Comparable<C>>
T max(List<T> list, int begin, int end)
i.e. T must have a super type that is comparable to itself. For example T cannot be Foo
class Foo implements Comparable<Object>
Foo does not make sense anyway; a Comparable can only be meaningfully compared to its own kind. The clause C extends Comparable<C> acknowledges that fact.
I have a couple of questions about generic wildcards in Java:
What is the difference between List<? extends T> and List<? super T>?
What is a bounded wildcard and what is an unbounded wildcard?
In your first question, <? extends T> and <? super T> are examples of bounded wildcards. An unbounded wildcard looks like <?>, and basically means <? extends Object>. It loosely means the generic can be any type. A bounded wildcard (<? extends T> or <? super T>) places a restriction on the type by saying that it either has to extend a specific type (<? extends T> is known as an upper bound), or has to be an ancestor of a specific type (<? super T> is known as a lower bound).
The Java Tutorials have some pretty good explanations of generics in the articles Wildcards and More Fun with Wildcards.
If you have a class hierarchy A, B is a subclass of A, and C and D are both subclasses of B like below
class A {}
class B extends A {}
class C extends B {}
class D extends B {}
Then
List<? extends A> la;
la = new ArrayList<B>();
la = new ArrayList<C>();
la = new ArrayList<D>();
List<? super B> lb;
lb = new ArrayList<A>(); //fine
lb = new ArrayList<C>(); //will not compile
public void someMethod(List<? extends B> lb) {
B b = lb.get(0); // is fine
lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B
}
public void otherMethod(List<? super B> lb) {
B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List<A> and only contain instances of A
lb.add(new B()); // is fine, as we know that it will be a super type of A
}
A bounded wildcard is like ? extends B where B is some type. That is, the type is unknown but a "bound" can be placed on it. In this case, it is bounded by some class, which is a subclass of B.
Josh Bloch also has a good explanation of when to use super and extends in this google io video talk where he mentions the Producer extends Consumer super mnemonic.
From the presentation slides:
Suppose you want to add bulk methods to Stack<E>
void pushAll(Collection<? extends E> src);
– src is an E producer
void popAll(Collection<? super E> dst);
– dst is an E consumer
There may be times when you'll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.
Collection<? extends MyObject>
means that it can accept all object who have IS- A relationship with MyObject (i.e. any object which is a type of myObject or we can say any object of any subclass of MyObject) or a object of MyObject class.
For example:
class MyObject {}
class YourObject extends MyObject{}
class OurObject extends MyObject{}
Then,
Collection<? extends MyObject> myObject;
will accept only MyObject or children of MyObject(i.e. any object of type OurObject or YourObject or MyObject, but not any object of superclass of MyObject).
In general,
If a structure contains elements with a type of the form ? extends E, we can get elements out of the structure, but we cannot put
elements into the structure
List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<? extends Number> nums = ints;
nums.add(3.14); // compile-time error
assert ints.toString().equals("[1, 2, 3.14]");
To put elements into the structure we need another kind of wildcard called Wildcards with super,
List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
List<Integer> ints = Arrays.asList(5, 6);
Collections.copy(objs, ints);
assert objs.toString().equals("[5, 6, four]");
public static <T> void copy(List<? super T> dst, List<? extends T> src) {
for (int i = 0; i < src.size(); i++) {
dst.set(i, src.get(i));
}
}
Generic wildcards are created to make methods that operate on Collection more reusable.
For example, if a method has a parameter List<A>, we can only give List<A> to this method. It is a waste for this method's funtion under some circumstances:
If this method only reads objects from List<A>, then we should be allowed to give List<A-sub> to this method. (Because A-sub IS a A)
If this method only inserts objects to List<A>, then we should be allowed to give List<A-super> to this method. (Because A IS a A-super)
learn by example:
consider the sort() method in Collections class which use both extends and super:
public static <T extends Comparable<? super T>> void sort(List<T> list){...}
so
why <T extends Comparable<...>>: becuase we need list items (T) to be a subclass of the Comparable interface.
why Comparable<? super T>: becuase we allow the Comparable type
to be a Comparable of any super type of T.
Consider
interface Comparable<T>{
public int compareTo(T o);
}
public static <T extends Comparable<? super T>> void sort(List<T> list){...}
public static <T extends Comparable<T>> void sort2(List<T> list){...}
class A implements Comparable<A>{
#Override
public int compareTo(A o) {
...
}
}
class B extends A {
}
List<A> listA = new ArrayList<>();
List<B> listB = new ArrayList<>();
sort(listA); //ok
sort(listB); //ok
sort2(listA); //ok
sort2(listB); //Error