Выведенный тип не является допустимым заменителем типа обобщенного типа
Рассмотрим код:
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)
будет работать.