简体   繁体   中英

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.

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>> <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
    }
}

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
    }
}

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM