Java "unchecked call to compareTo(T) as a member of the raw type java.lang.Comparable"

31.4k views Asked by At

I'm trying to implement a sorted list as a simple exercise in Java. To make it generic I have an add(Comparable obj) so I can use it with any class that implements the Comparable interface.

But, when I use obj.compareTo(...) anywhere in the code I get "unchecked call to compareTo(T) as a member of the raw type java.lang.Comparable" from the compiler (with -Xlint:unchecked option). The code works just fine but I can't figure out how to get rid of that annoying message.

Any hints?

3

There are 3 answers

2
axtavt On BEST ANSWER

In essence, this warning says that Comparable object can't be compared to arbitrary objects. Comparable<T> is a generic interface, where type parameter T specifies the type of the object this object can be compared to.

So, in order to use Comparable<T> correctly, you need to make your sorted list generic, to express a constraint that your list stores objects that can be compared to each other, something like this:

public class SortedList<T extends Comparable<? super T>> {
    public void add(T obj) { ... }
    ...
}
0
D.N. On

You need to "check" or define the Comparable object like so:

add(Comparable<Object> obj)
0
Bert F On

Using an interface like Comparable as a method parameter doesn't make your class generic, declaring and using generic type parameters is how you make it generic.

Quick-n-dirty answer: You are receiving the warning because you are using Comparable, which is a generic interface, as a raw type, rather than giving it a specific type arguments, like Comparable<String>.

To fix this, make add() generic by specifying type parameters:

<T extends Comparable<? super T>> add(T obj) { ... }

But this quick fix won't fix the general problem that your class is unsafe. After all, shouldn't all the objects in your list be of the same type? This add method lets you still different types into the same list. What happens when you try to compare heterogeneous types (how do you compareTo an Object instance to an Number instance, or to a String instance)? You can depend on the user of the class to do the right thing and ensure they only stick 1 kind of thing in your list, but a generic class will let the compiler enforce this rule.

The better approach: The proper fix is that your sorted list class should be probably be generic overall, just like the other collection classes in java.util.

You would probably like something like:

public class SortedList<T extends Comparable<? super T>>
implements Iterable<T> {
    ...
    public void add(T item) { ... }
    public Iterator<T> iterator() { ... }
    ...
}

Note that when the class is generic, the add method uses the classes formal type parameter rather than declaring its own formal type parameter.

There should be plenty of tutorials on the web on how to create a generic class, but here's a quick example:

http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#FAQ002

class Pair<X,Y>  {  
  private X first; 
  private Y second;
  public Pair(X a1, Y a2) { 
    first  = a1; 
    second = a2; 
  } 
  public X getFirst()  { return first; } 
  public Y getSecond() { return second; } 
  public void setFirst(X arg)  { first = arg; } 
  public void setSecond(Y arg) { second = arg; } 
}