Reputation: 475
I want to define a class that implements the generic Comparable interface. While in my class I also defined a generic type element T
. In order to implement the interface, I delegate the comparison to T
. Here is my code:
public class Item<T extends Comparable<T>> implements Comparable<Item> {
private int s;
private T t;
public T getT() {
return t;
}
@Override
public int compareTo(Item o) {
return getT().compareTo(o.getT());
}
}
When I try to compile it, I get the following error information:
Item.java:11: error: method compareTo in interface Comparable<T#2> cannot be applied to given types;
return getT().compareTo(o.getT());
^
required: T#1
found: Comparable
reason: actual argument Comparable cannot be converted to T#1 by method invocation conversion
where T#1,T#2 are type-variables:
T#1 extends Comparable<T#1> declared in class Item
T#2 extends Object declared in interface Comparable
1 error
Can anybody tell me why and how to fix it?
Upvotes: 27
Views: 93313
Reputation: 311
A bit of a related issue that I ran into, and couldn't find a concrete answer.
Suppose you have an interface
public interface myInt extends Comparable<myInt>
And a class MyClass
that implements myInt
.
Now you only want to compare MyClass
with MyClass
objects. How should we rewrite the interface and the class?
Answer:
public interface myInt<T extends myInt<T>> extends Comparable<T>
public class MyClass implements myInt<MyClass>
Upvotes: 0
Reputation: 37845
Item
(without any type argument) is a raw type, so:
We could pass any kind of Item
to Item.compareTo
. For example, this would compile:
new Item<String>().compareTo(new Item<Integer>())
The method o.getT()
returns Comparable
instead of T
, which causes the compilation error.
In the example under the 1st point, after passing Item<Integer>
to Item.compareTo
, we would then erroneously pass an Integer
to String.compareTo
. The compilation error prevents us from writing the code which does that.
I think you just need to remove the raw types:
public class Item<T extends Comparable<T>>
implements Comparable<Item<T>> {
...
@Override
public int compareTo(Item<T> o) {
return getT().compareTo(o.getT());
}
}
Upvotes: 27
Reputation: 202
I think, this makes more sense. I have compiled and tested the following :
class Item<E extends Comparable<E>> implements Comparable<E> {
private int s;
private E t;
public E getE() {
return t;
}
@Override
public int compareTo(E e) {
return getE().compareTo(e);
}
public int compareTo(Item<E> other)
{
return getE().compareTo(other.getE());
}
}
Notice that you now need to have two compareTo methods.
Upvotes: 1
Reputation: 3279
You're using raw types in your class definition (Item<T>
is generic, but you're omitting the type parameter <T>
), change it to:
class Item<T extends Comparable<T>> implements Comparable<Item<T>>
(Note the last <T>
)
The compareTo
method will then have to be changed as well:
public int compareTo(Item<T> o) { // again, use generics
return getT().compareTo(o.getT());
}
Upvotes: 10