Как поймать конкретное исключение времени выполнения с помощью библиотеки Vavr (ранее известной как Javaslang)?

Я пытаюсь перехватить конкретное исключение времени выполнения (поэтому его нельзя выбросить) и просто зарегистрировать его (log.error имеет тип возврата void). Как проще всего это сделать в вавре?

try {
    sayHello();
} catch (MyAppRuntimeException ex) {
    log.error("Error occured") // log.error returns void not Void so I couldn't find a suitable method in  Vavr library
}

я пытался

Try.run(() -> sayHello())
   .recover(MyAppRuntimeException.class, ex->log.error("Error occured: {}", ex.getMessage()))

Я получил:

Неверный тип возвращаемого значения void не может быть преобразован в Void

Если .recover - неправильный метод, предложите альтернативы, в которых я могу поймать одно конкретное исключение, но не Throwable, поскольку он улавливает все исключения и ошибки.


person user1870400    schedule 16.10.2017    source источник


Ответы (1)


Объяснить это довольно просто. Ваш метод - это не указано явно, но я предполагаю, что на основе сообщения об ошибке возвращается void. Поскольку recover также должен возвращать значение, необходимое для дальнейшей обработки, совместимое с типом, возвращаемым из методов, которые он обертывает, он должен возвращать Void, поэтому:

Итак, код будет:

Try
   .run(this::sayHello)
   .recover(MyAppRuntimeException.class, e -> {
      log.error("Error occured: {}", e.getMessage());
      return null;
   });

Взгляните на docs.

ИЗМЕНИТЬ

После обсуждения в комментариях выяснилось, что рекавери - это не то, что нужно. Эта функция используется для предоставления значения восстановления, а не для регистрации оператора, поэтому onFailure + instanceof (вместо сопоставления с образцом), похоже, выполняет свою работу:

Try
   .run(this::sayHello)
   .onFailure(throwable -> {
      if (throwable instanceof MyAppRuntimeException) {
         log.error("Error occured: {}", throwable.getMessage());
      } else {
         throw new RuntimeException(throwable);
      }
   })
person Opal    schedule 16.10.2017
comment
Я искал более чистый способ, если не восстановить какой-либо другой вызов API, но я ничего не нашел в документах и. да sayHello () возвращает void. Если мне нужно возвращать null для каждого оператора журнала, я мог бы просто использовать обычный try / catch Java, поскольку он выглядел бы более чище. - person user1870400; 16.10.2017
comment
@ user1870400, более чистый способ - использовать метод onFailure. Он принимает экземпляр Consumer, поэтому ему нужно что-то возвращать. - person Opal; 17.10.2017
comment
onFailure выглядит так, как будто он принимает throwable. Я не хочу ловить throwable, так как он перехватит все исключения и ошибки. Я только хочу поймать MyAppRuntimeException. Просьба уточнить - person user1870400; 17.10.2017
comment
Да, ты прав. Другой способ сделать это - использовать сопоставление с образцом, которое в этом простом случае могло бы стать проблемой. Восстановление не предназначено для регистрации оператора, а для предоставления значения повторного восстановления. onFailure - это то, что вам нужно - вы всегда можете использовать instanceof. - person Opal; 17.10.2017
comment
Я думаю, вы обратили внимание на метод восстановления. Не могли бы вы обновить ответ, используя onFailure и instanceOf? так что я могу принять ответ. Это тоже помогло бы мне. Большое спасибо! ЕСЛИ экземпляр проверки завершился неудачно, я бы хотел, чтобы исключение выдавалось как обычно. - person user1870400; 17.10.2017
comment
Что произойдет, если throwable instanceof MyAppRuntimeException проверка не удалась? - person user1870400; 17.10.2017
comment
скажем, у меня есть другое исключение, отличное от MyAppRuntimeException, и скажем, что проверка throwable instanceof MyAppRuntimeException не сработает, будет ли выбрано это исключение? или я отловлю все исключения и ошибки? - person user1870400; 17.10.2017
comment
Думаю, было бы еще быстрее, если бы ты сам попробовал. Если эта проверка не удалась, ничего не происходит, так как else нет. Все исключения будут переданы этому методу, но действие будет выполнено только для MyAppRuntimeException. - person Opal; 17.10.2017
comment
да, но я бы хотел, чтобы в соответствии с моим вопросом, если проверка не удалась, она должна была сработать как обычно. так как я пытаюсь поймать только одно конкретное исключение и выбросить все остальное. В приведенном выше примере я действительно могу войти в журнал при возникновении MyAppRuntimeException, но я также буду хранить молчание, если будет какое-либо другое исключение. Я не хочу молчать, если есть какие-либо другие исключения или ошибки. похоже, что Vavr недостаточно зрел, чтобы обрабатывать исключения! - person user1870400; 17.10.2017
comment
Действительно, у vavr есть некоторые ограничения, но я утверждаю, что он достаточно зрелый и очень популярный. Это по некоторым причинам. Чего вы пытаетесь достичь? onFailure - это просто потребитель, вы можете регистрировать любые исключения там. Вначале вы хотели один, теперь вы жалуетесь, что он регистрирует только один. Я не понимаю. - person Opal; 17.10.2017
comment
хорошо, я не уверен, что вам непонятно. Но моя цель проста. Я хочу регистрировать, когда я получаю конкретное исключение MyAppRuntimeException, и если возникает какое-либо другое исключение RuntimeException или ошибка, я хочу, чтобы они выдавались, как и любая другая программа Java. В приведенном вами примере он будет молчать, так как перехватывает Throwable. это достаточно ясно? - person user1870400; 17.10.2017
comment
Похоже, вам не хватает базового понимания того, как работает vavr :( onFailure работает как peek - просто позволяет вам видеть, что происходит внутри потока. Возникло ли исключение или нет на этапе позже. другое дело. - person Opal; 17.10.2017
comment
Правда не понимаю, как это работает! И я не понимаю даже сейчас. Хорошо, скажем, у меня есть MyAppRuntimeException и DivisionByZeroException. теперь я хочу регистрировать, когда происходит MyAppRuntimeException, и просто бросать, если возникает DivisionByZeroException или любое другое исключение. так что onFailure вызывается, когда в программе есть исключение, верно ?! Если так, я бы проверил и посмотрел, что это за исключение. если это MyAppRuntimeException, я регистрирую это, а если это DivisionByZeroException, я просто хочу выбросить это исключение, но не молчать. - person user1870400; 17.10.2017
comment
Затем оставьте код как есть и добавьте get (или любой другой метод, разрешающий цепочку) в конце, что является функциональным, но в случае его возникновения вызовет исключение. - person Opal; 17.10.2017
comment
@ user1870400, вместо вызова get вы можете выбросить исключение из ветки else, однако вам нужно обернуть его в RuntimeException. - person Opal; 17.10.2017
comment
понятно! будет явно использовать throw, как вы показали, но вы можете видеть, что это большое ограничение библиотеки Vavr. Я не верю, что Vavr хороший вызов Api для обработки исключений, поскольку все моделируется на основе Throwable. Есть и другие люди, которые сталкиваются с той же проблемой. github.com/vavr-io/vavr/issues/2137 - person user1870400; 17.10.2017
comment
Это может быть правдой, однако vavr также предполагает (я полагаю), что yon не будет генерировать исключение, а будет обрабатывать его, если оно произойдет. - person Opal; 17.10.2017
comment
да, я не хочу ловить и выбрасывать исключения таким образом. это действительно взлом из-за плохого дизайна интерфейса Vavr в этом аспекте. вы можете взглянуть на этот билет и увидеть, что уже предлагали другие люди. Они хотят <E extends Exception> вместо <? Extends Throwable>. Это имеет огромное значение - person user1870400; 18.10.2017
comment
с библиотекой Cyclops я могу легко сделать следующее для моего вышеупомянутого вопроса Try.catchExceptions(MyAppRuntimeException.class) .try(() -> sayHello()) .onFail(MyAppRuntimeException.class, log.error("Error occured: {}", e.getMessage())) Хотя мне больше нравится Vavr, чем Cyclops. Я думаю, что у Cyclops сейчас лучшая обработка исключений, чем у Vavr. - person user1870400; 18.10.2017
comment
Если throwable будет проверено исключение, ваш код повторно выбрасывает его как непроверенный, что не является хорошим стилем кода. - person stand alone; 29.01.2020
comment
Почему? Я вижу, что в настоящее время разработчики стараются избегать проверенных исключений. - person Opal; 30.01.2020