Почему метод сравнения Comparator, созданный с использованием шаблона, не может принять объект? - PullRequest
1 голос
/ 13 января 2020

В Java допустимо создать объект сравнения, подобный этому:

Comparator<? super Number> comparator = new Comparator<Object>() {
    @Override
    public int compare(Object o1, Object o2) {
        // implementation here
    }
};

Но вы не можете использовать этот объект для простого вызова, подобного этому:

Object o1 = new Object(), o2 = new Object();
comparator.compare(o1, o2);

Почему так? Я думал, ? super Number означает число и все его суперклассы.

Ответы [ 3 ]

3 голосов
/ 13 января 2020

Предположим, вместо этого вы использовали ? super Double:

Comparator<? super Double> comparator = new Comparator<Object>() {
    // ...
};

То, что вы говорите компилятору, это то, что у вас есть компаратор, который

  • может быть a Comparator<Double>, или
  • может быть a Comparator<Number>, или
  • , может быть a Comparator<Object> или
  • может быть a Comparator<Serializable>.

Даже если вы инициализировали его с Comparator<Object>, компилятор не знает этого, потому что компилятор не выполнить код. Компилятор знает только, что переменная содержит компаратор одного из указанных выше типов.

Поскольку переменная может содержать компаратор типа, более специфичного c, чем Object, компилятор будет не предполагайте, что все в порядке, чтобы передать объект.

2 голосов
/ 13 января 2020

Comparator<? super Number> comparator означает, что comparator относится к чему-то, о чем известно, что оно может принять Number (или null).

A Comparator<Object> может принять Number; но компилятор не знает, является ли значение, на которое ссылается Comparator<? super Number>, Comparator<Object> или Comparator<Number>. Все, что он знает, это то, что он может принять Number, так что это все, что он позволит вам пройти.

Почему так? Я думал, что ? super Number означает число и все его суперклассы.

Нет: это означает, что Number является приемлемым типом для передачи в качестве параметра. Другими словами, Number является подтипом допустимого типа параметра. Иными словами, приемлемый тип параметра - это супертип Number, поэтому можно передать Number.

См .: Что такое PECS (Producer Extends Consumer Super)?

1 голос
/ 13 января 2020

Причина, по которой o1 и o2 нельзя использовать в качестве параметров, заключается в том, что они "более общие", чем Number, и, следовательно, они могут указывать на экземпляр класса, который является частью другой иерархии, начиная с некоторой точки в родительской цепочке Number. Что-то типа класса Son находится непосредственно в иерархической строке Father, но не в иерархии Grandfather класса SecondSon. Таким образом, ссылка на экземпляр класса Grandfather не может быть передана, поскольку она может указывать на экземпляр в иерархии SecondSon.

Я пытался объяснить аналогичную точку здесь .

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