Сопоставимые и универсальные модели Wilcard - PullRequest
2 голосов
/ 14 ноября 2011

Предположим, у меня есть следующий класс (для демонстрационных целей)

package flourish.lang.data;
public class Toyset implements Comparable<Toyset> {
    private Comparable<?>[] trains;

    @Override
    public int compareTo(Toyset o) {
        for (int i =0; i<trains.length; i++) {
            if (trains[i].compareTo(o.trains[i]) < 0)
                return -1;
        }
        return 1;
     }  
}

Компилятор сообщает мне

"Метод compareTo (capture # 1-of?) Втип Comparable<capture#1-of ?> не применим к аргументам (Comparable<capture#2-of ?>) "

Как я могу справиться с тем фактом, что я хочу добавить в поезда разные Comparables?Конечно, я мог бы удалить параметры и перейти к необработанным типам, но это выглядит как отрывок.

РЕДАКТИРОВАТЬ: Возможно, пример, который я привел, немного туповат.Я пытаюсь понять, всегда ли дженерики должны использоваться с Comparables.Например, если класс объекта, который я хочу сравнить, не известен до времени выполнения:

public class ComparisonTool {
    public static int compareSomeObjects(final Class<? extends Comparable> clazz, final Object o1, final Object o2) {
        return clazz.cast(o1).compareTo(clazz.cast(o2));
    }

    public static void main(String[] args) {
        System.out.println(compareSomeObjects(Integer.class, new Integer(22), new Integer(33)));
    }
}

Если я заменим Comparable на Comparable<?>, то компилятор жалуется (как указано выше), потому что две операции приведения не являютсягарантированно будет один и тот же класс (захват № 1 из? против захвата № 2 из?).С другой стороны, я также не могу заменить их на Comparable<Object>, потому что тогда вызов в main() не соответствует сигнатуре метода (т. Е. Integer реализует Comparable<Integer>, а не Comparable<Object>. Использование rawТип, конечно, «работает», но это правильный подход?

Ответы [ 2 ]

4 голосов
/ 14 ноября 2011

Проблема заключается в том, что один экземпляр может иметь Comparable<TrainA>, а другой - Comapable<TrainB>, а метод compare для Comparable<TrainA> не будет принимать экземпляр TrainB. Это то, что вы установили с подстановочным знаком.

Лучше ставить общий супер тип в Comparable, т.е. Comparable<Toy> или Comparable<Object>.

0 голосов
/ 15 ноября 2011

Объявляя ваше поле trains типа Comparable<?>[], вы утверждаете, что это массив какого-то определенного типа & mdash; и вы не знаете, какой тип это , Каждое из двух экземпляров Toyset будет иметь поля trains, которые содержат последовательности определенного типа , но каждый из них имеет в виду другой определенный тип. Компилятор предупреждает вас, что в коде нет ничего, утверждающего, что определенные типы массивов, указанные как различные поля trains в Toyset экземплярах, будут иметь отношение любого подтипа или супертипа.

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

Дизайн кажется мне странным. Я предполагаю, что это исключено из чего-то намного большего. Можно сравнивать игрушечные наборы, что, в свою очередь, зависит от лексикографического сравнения поездов, содержащихся в каждом игрушечном наборе. Это хорошо, но почему нет типа верхней границы, который есть у всех поездов?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...