Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inferred type is not a valid substitute for a Comparable generic type

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.

like image 356
terrorcell Avatar asked Jul 19 '13 06:07

terrorcell


2 Answers

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
    }
}
like image 64
Andremoniy Avatar answered Sep 18 '22 16:09

Andremoniy


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
    }
}
like image 25
Bernhard Barker Avatar answered Sep 21 '22 16:09

Bernhard Barker