Reputation: 187
Consider the code:
public abstract class Item<T> implements Comparable<T>
{
protected T item;
public int compareTo(T o)
{
return 0; // this doesn't matter for the time being
}
}
public class MyItem<T> extends Item<String>
{
T object;
}
public class Foo<T>
{
protected ArrayList<T> list;
}
public class Bar<V> extends Foo<MyItem<V>>
{
public void sort()
{
Collections.sort(list);
}
}
The sort call gives the error:
Bound mismatch: The generic method sort(List< T >) of type Collections is not applicable for the arguments (ArrayList< MyItem< T > >). The inferred type MyItem< T > is not a valid substitute for the bounded parameter < T extends Comparable< ? super T > >
Why is this wrong?
If MyItem<V>
implements Comparable
then why is it not a substitute?
Sorry if this has been asked, but I feel the question is somewhat specific.
Upvotes: 14
Views: 18496
Reputation: 34920
Actually more detailed explanation of this error gives your javac
itself:
java: no suitable method found for
sort(java.util.ArrayList<MyItem<V>>
)method
java.util.Collections.<T>sort(java.util.List<T>,java.util.Comparator<? super T>)
is not applicable (cannot instantiate from arguments because actual and formal argument lists differ in length)method
java.util.Collections.<T>sort(java.util.List<T>)
is not applicable (inferred type does not conform to declared bound(s) inferred:MyItem<V>
bound(s):java.lang.Comparable<? super MyItem<V>>
)
So, the main question is:
why is method Collections.<T>sort(java.util.List<T>)
) not applicable?
The answer is:
because in Collections.<T>sort(java.util.List<T>)
method declaration there are bounds on parameter T
: <T extends Comparable<? super T>>
.
In another words, T
must implement Comparable
interface on it self. For example String
class implements such interface: ...implements ... Comparable<String>
.
In your case Item
class doesn't implement such interface:
Item<T> implements Comparable<T>
is not same thing as Item<T> implements Comparable<Item<T>>
.
So, for solving this problem, your should change your Item
class to this one:
public abstract class Item<T> implements Comparable<Item<T>>
{
protected T item;
public int compareTo(Item<T> o)
{
return 0; // this doesn't matter for the time being
}
}
Upvotes: 12
Reputation: 55619
For objects of type X
to be comparable with each other, class X
has to implement exactly Comparable<X>
.
This is not what your code is doing, you've got a class Item<T>
and you are implementing Comparable<T>
instead of Comparable<Item<T>>
. This means that Item<T>
can be compared with T
, but not with Item<T>
, which is required.
Change your Item<T>
class to:
public abstract class Item<T> implements Comparable<Item<T>>
{
protected T item;
@Override
public int compareTo(Item<T> o)
{
return 0; // this doesn't matter for the time being
}
}
Upvotes: 2
Reputation: 604
Just change the class like follow:
public class MyItem<T> extends Item<String> implement Comparable<MyItem<T>>
{
T object;
}
Or
public abstract class Item<T> implements Comparable<MyItem<T>>
{
protected T item;
public int compareTo(MyItem<T> o)
{
return 0; // this doesn't matter for the time being
}
}
The error tips has shown us.Hope it helpful.
Upvotes: 1
Reputation: 20648
You do not need to have the class MyItem
generified just to see the effect. The following class is enough to see what happens:
public class MyItem extends Item<String> {}
Now you have the following call:
Collections.sort(list);
As morgano stated correctly, the sort method will take a collection that is parameterized with a type T that must be comparable to T. Your MyItem
class is extending Item<String>
, which results in MyItem
being comparable to String
s.
With a little switch in which class implements the Comparable
interface, you will get the expected result:
public abstract class Item<T> {
protected T item;
}
public class MyItem extends Item<String> implements Comparable<MyItem> {
@Override
public int compareTo(MyItem o) {
return item.compareTo(o.item); // just an example
}
}
And now the call to Collections.sort(list)
will work.
Upvotes: 0