27

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?

3
  • 2
    Not 100% sure, but should this: compareTo(Item o) be compareTo(Item<T> o)? Commented Feb 4, 2014 at 5:41
  • 3
    for best results use <T extends Comparable<? super T>> Commented Feb 4, 2014 at 21:32
  • You should select an answer for this question. Commented Mar 27, 2017 at 1:28

4 Answers 4

27

Item (without any type argument) is a raw type, so:

  1. We could pass any kind of Item to Item.compareTo. For example, this would compile:

    new Item<String>().compareTo(new Item<Integer>())
    
  2. 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());
    }
}
Sign up to request clarification or add additional context in comments.

Comments

10

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());
}

Comments

1

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.

6 Comments

The asker wants items to be comparable (by comparing their values).
It's possible if T implements Comparable, which is the case here.
Ya, please have a look at the other solution that I have given now.
Your answer doesn't make much sense at all. "we are extending comparable and not implementing it." - one implements interfaces and extends classes. extends is used in generics for both cases though. "because we are using a generic type T, we must not override compareTo method" - generic types don't prevent us from implementing interfaces, e.g. ArrayList<T> implements List<T>. "T can be anything [...] Specifically, it has to be something that is Comparable" - T already is Comparable, in both the OP's code and your code, in particular it is comparable to itself.
That's certainly better.
|
0

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.