Java: почему я не могу выбросить исключение в Comparator? - PullRequest
6 голосов
/ 30 сентября 2010

Прямой ответ заключается в том, что интерфейс Comparator.compare указан так, что он не генерирует исключения. Но почему это так?

Или, если выразиться иначе: мой Comparator должен зависеть от функции, которая может генерировать исключение. Теоретически этого не должно быть. Но если это произойдет, я хочу, чтобы это вырвалось из всей функции, где я использую это ComparatorCollections.sort). То есть Я хочу, чтобы он просто вел себя так, как будто произошло необработанное исключение.

Кажется, что это невозможно естественным образом (потому что, если интерфейс говорит, что он не может вызвать исключение, он не может).

Как бы я решил это? С безобразной попыткой / поймать и распечатать исключение и надеюсь, что я его узнаю? Это выглядит довольно уродливо.

Ответы [ 8 ]

13 голосов
/ 30 сентября 2010

Вы всегда можете выдать RuntimeException или его производное, даже от метода, явно не объявляющего себя для выдачи исключений.

5 голосов
/ 30 сентября 2010

В этом случае я бы сбросил AssertionError, поскольку вы предполагаете, что исключение не может быть вызвано.Не забудьте использовать метод initCause() для распространения информации (AssertionError не имеет конструктора, принимающего Throwable)

3 голосов
/ 30 сентября 2010

Это контракт метода Comparator.compare.Если вы хотите использовать его, вы должны просто следовать правилу, чтобы не выбрасывать проверенные исключения из него :) Между тем, вы можете выбросить непроверенное исключение ( RuntimeException или его подкласс), и это не нарушит контракт.

2 голосов
/ 30 сентября 2010

Это потому, что вы не аннотировали свой метод аннотацией @ SneakyThrows Lombok.
Проверьте это в http://projectlombok.org/features/SneakyThrows.html

Также стоит посмотреть демонстрацию и слайды на домашней странице Lombok http://projectlombok.org/

1 голос
/ 30 сентября 2010

Вы задаете разные вопросы в заголовке вопроса и в теле вопроса.

Вы не знаете, почему функция с поддержкой исключений, используемая методом compare(), выдает исключение.Это либо потому, что в коллекции есть определенные несопоставимые объекты (например, NaN числовое значение), либо потому, что существуют определенные пары объектов, которые нельзя сравнивать друг с другом.

Почему можноя выбрасываю исключение в Comparator?

Я думаю, Comparator.compare() не предназначен для создания проверенного исключения, потому что:

  1. этоПредполагается, что любые элементы, которые вы хотите сравнить / отсортировать, всегда будут сопоставимы.

  2. , если Comparator.compare() может вызвать какое-то ожидаемое (то есть проверенное) исключение, тогда я могу представитьпара нежелательных сценариев:

    a.сортировка может быть прервана, потому что там находится какой-то несопоставимый объект - вероятным ответом будет удаление несопоставимых объектов и повторная попытка сортировки

    b.множественные сортировки в разных порядках одного и того же набора объектов могут иногда прерываться с исключением, а иногда и успешно, в зависимости от того, выпала ли пара несопоставимых объектов для сравнения во время сортировки

Это, конечно, только моя гипотеза.

Как бы я решил это?

Я собираюсь предположить, что причина, по которой функция-исключение, которую использует Comparator.compare(), генерирует исключение, заключается в том, что в коллекции есть несопоставимый объект (например, числовое значение NaN).Возможные варианты:

  1. Сортировать копию списка с удаленными несопоставимыми объектами.

  2. Бросить непроверенное (во время выполнения) исключение впрервать сортировку.Не уверен, что вы будете делать тогда, кроме # 1 выше.

  3. Следуйте подходу NaN и сделайте так, чтобы эти объекты появлялись в начале или в конце.

    NaN значения обычно несопоставимы с другими значениями, но во время сортировки компаратор определяет свой собственный общий порядок, так что значения NaN заканчиваются в конце отсортированной коллекции.

    http://download.oracle.com/javase/1.4.2/docs/api/java/util/Arrays.html#sort(double[])

    ... Отношение <не обеспечивает полный порядок для всех значений с плавающей точкой;... значение NaN сравнивается не меньше, не больше, не равно и не равно какому-либо значению с плавающей запятой, даже самому себе. </p>

    ... Чтобы разрешить продолжение сортировки, ... этот метод использует итоговое значениепорядок, налагаемый Double.compareTo (java.lang.Double).

    ... Этот порядок отличается от отношения <тем, что ... NaN считается больше, чем любое другое значение с плавающей запятой.Для целей сортировки все значения NaN считаются эквивалентными и равными. </p>

    Для этого кодируйте Comparator.compare() так, чтобы любой несравненный объект всегда сравнивался с большим значением, чем любой сопоставимый объект, и всегда сравнивался равнымк любому другому несравненному объекту.

0 голосов
/ 19 октября 2018

В этой статье описывается, почему выбрасывать RuntimeException из интерфейса Comparator - плохая идея, и в нем показан пример исходного кода для двух полезных способов обработки проверенных исключений из интерфейсов, которые их не поддерживают:задача на две части, или 2) используйте свой собственный компаратор, который поддерживает проверенные исключения.

https://www.ibm.com/developerworks/library/j-ce/index.html

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

0 голосов
/ 01 октября 2010

Вы можете перебросить проверенное исключение и избежать ошибки компиляции, используя ряд приемов. Самый простой;

try {
   // something
} catch (Exception e) {
   Thread.currentThread().stop(e);
}

Однако, поскольку компилятор понятия не имеет, вы сделали это. Вы можете запутать это и себя, если не будете осторожны. Одна из целей замыканий - правильно обрабатывать проверенные исключения в таких вещах, как Comparators (в то время как другие предпочитают, чтобы они ушли)

0 голосов
/ 30 сентября 2010

Существует два способа решения этой проблемы:

  1. Перехват исключения и его выброс в java.lang.RuntimeException() или
  2. Перехват исключения и запись его в журнал с помощью Log4J или SLF4J (или любой завод по производству лесозаготовок, с которым вам удобно).

Контракт для метода сравнения компаратора не вызывает исключений.

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