Comparator.reverseOrder() и natural ordering — рабочий код до Comparable без реализации

Comparator.reverseOrder() — метод-ловушка, потому что он компилируется всегда, а падает только в runtime, и только на конкретных типах.

Сигнатура: static > Comparator reverseOrder(). Он требует, чтобы тип реализовывал Comparable, и просто разворачивает natural ordering — то, что вернул бы compareTo(), умноженное на минус один.

Код с обычными типами — String, Integer, LocalDate — работает без вопросов, потому что все они реализуют Comparable. Проблема начинается, когда его подставляют для собственного класса без Comparable:

public class Task { private final String name; private final int priority;

// конструктор, геттеры }

List tasks = new ArrayList<>(); tasks.sort(Comparator.reverseOrder());

Это не компилируется — и это единственная защита, которую даёт компилятор. Если разработчик реализует Comparable формально, просто чтобы код скомпилировался, а внутри compareTo() сравнивает не то поле, которое ожидается по бизнес-логике — reverseOrder() развернёт именно эту, ошибочную, логику.

На собеседовании спросят: чем Comparator.reverseOrder() отличается от comparator.reversed(). Первый — статический метод, разворачивает natural ordering объекта, требует Comparable. Второй — метод экземпляра на уже существующем Comparator, разворачивает именно ту логику сравнения, что заложена в этом компараторе, и не требует Comparable вообще. Путают их, потому что оба возвращают «развёрнутый» результат, но исходная логика сравнения у них разная по природе.

Разворот сортировки — это не инверсия результата, это инверсия конкретной логики сравнения. Если логика в compareTo() ошибочна, разворот просто ошибается в другую сторону.

Тренажёр: 600 вопросов, мок с таймером, план повторов

senior·base — что спрашивают на самом деле


В этом посте были ссылки, но мы их удалили по правилам Сетки