Выведенный тип не является допустимым заменителем типа обобщенного типа

Рассмотрим код:

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


Вызов сортировки дает ошибку:

Связанное несоответствие: общий тип метода (List <T> ) типа Collections не применим для аргументов (ArrayList < MyItem < T → ). Выведенный тип MyItem <T> не является допустимым подстановкой для ограниченного параметра < T расширяет Сопоставимый <? super T →


Почему это неправильно?

Если MyItem<V> реализует Comparable, то почему он не заменяет?

Извините, если это было задано, но я чувствую, что вопрос несколько конкретный.

Ответ 1

На самом деле более подробное объяснение этой ошибки дает ваш javac сам:

java: нет подходящего метода для sort(java.util.ArrayList<MyItem<V>>)

метод java.util.Collections.<T>sort(java.util.List<T>,java.util.Comparator<? super T>) не применим (не может быть экземпляр из аргументов, потому что фактические и формальные списки аргументов различаются по длине)

метод java.util.Collections.<T>sort(java.util.List<T>) не применим (предполагаемый тип не соответствует объявленным границам (-ам): MyItem<V> bound (s): java.lang.Comparable<? super MyItem<V>>)

Итак, главный вопрос:
почему метод Collections.<T>sort(java.util.List<T>)) не применим?

Ответ:
потому что в объявлении метода Collections.<T>sort(java.util.List<T>) существуют ограничения на параметр T: <T extends Comparable<? super T>>.

Другими словами, T должен реализовать интерфейс Comparable на себе. Например, класс String реализует такой интерфейс: ...implements ... Comparable<String>.

В вашем случае класс Item не реализует такой интерфейс:

Item<T> implements Comparable<T> не то же самое, что Item<T> implements Comparable<Item<T>>.

Итак, для решения этой проблемы ваш класс должен изменить ваш класс Item:

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

Ответ 2

Для объектов типа X, которые должны быть сопоставимы друг с другом, класс X должен реализовать точно Comparable<X>.

Это не то, что делает ваш код, у вас есть класс Item<T>, и вы используете Comparable<T> вместо Comparable<Item<T>>. Это означает, что Item<T> можно сравнить с T, но не с Item<T>, что требуется.

Измените класс Item<T> на:

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

Ответ 3

Просто измените класс следующим образом:

     public class MyItem<T> extends Item<String> implement Comparable<MyItem<T>>
     {
         T object;
     }

или

       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
       }

}

Советы по ошибкам показали нам. Надеюсь, что это будет полезно.

Ответ 4

Вам не нужно генерировать класс MyItem, чтобы увидеть эффект. Следующий класс достаточно, чтобы увидеть, что происходит:

public class MyItem extends Item<String> {}

Теперь у вас есть следующий вызов:

Collections.sort(list);

Как утверждается Morgano, метод сортировки возьмет коллекцию, которая параметризуется типом T, который должен быть сопоставим с T. Ваш класс MyItem расширяется Item<String>, что приводит к тому, что MyItem сравнимо с String s.

С небольшим переключением, в котором класс реализует интерфейс Comparable, вы получите ожидаемый результат:

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

И теперь вызов Collections.sort(list) будет работать.