Возврат исключения по умолчанию / универсального для необязательного orElseThrow - PullRequest
0 голосов
/ 24 июня 2019

Я не уверен насчет названия моего вопроса, но вот моя проблема. У меня есть этот код ниже:

return Optional.of(t).filter(p -> {
    PolicyNumber test = (PolicyNumber) p;

    return service.getAndValidate(p).test(p);
}).map(p -> {
    return p;
}).orElseThrow(() -> {
    return null;
});

Метод getAndValidate работает нормально, но когда я попадаю в блок map (это то, что вы называете?), Возникает ошибка. Раньше я использовал try...catch и мог просто написать что-то вроде:

try {
    //some code
} catch (Exception e) {
    e.printStackTrace();
}

И с этим я легко могу понять, что такое суета. Мне было интересно, как я могу сделать это для Optional. Я довольно новичок в этом, и я пытаюсь быть немного осведомленным с этим. Я проверил учебники в Интернете, но большая часть того, что я вижу, требует, чтобы у меня был класс с заранее определенными сообщениями, которые будут использоваться как сообщения об исключениях. Если я просто использую return null;, очевидно, я не получу никакого сообщения об ошибке и не узнаю, какая ошибка была вызвана. Любое предложение будет оценено

Ответы [ 2 ]

0 голосов
/ 27 июня 2019

Кажется, вам нужно немного подробнее изучить класс Optional, а затем, возможно, опубликовать код, который работает без опций, используя try ... catch, то есть полный метод и то, что вы хотите сделать.А пока я отвечу, сделав предположение.

Предполагая, что у вас есть метод, подобный следующему, где вы хотите протестировать и вернуть объект, в то же время регистрируя и игнорируя любые исключения в обернутой логике проверки:

static class Service {

    public <T> Predicate<T> getAndValidate(final T t) {
        return null;
    }
}

static <T> T test(final T t) {
    final Service service = null; // need to initialize properly

    // code without optional
    try {
        if (t != null) {
            if (service.getAndValidate(t).test(t)) {
                return t;
            }
        }
    } catch (final Exception e) {
        e.printStackTrace();
    }

    return null;
}

Теперь вы можете получить тот же код, но не многословно, используя Optional.Вам не нужен map с функцией идентификации, вы можете просто использовать filter и обернуть вызов службы командой try ... catch.

static <T> T test(final T t) {
    final Service service = null;

    return Optional.ofNullable(t)
            .filter(p -> {
                try { // you can also wrap it with try..catch
                    return service.getAndValidate(p).test(p);
                } catch (final Exception e) {
                    e.printStackTrace();
                    return false; // filter element on exception
                }
            }).orElse(null);

}

Однако я бы переосмыслил дизайн этого метода,Прежде всего, поймать Exception вместо определенного подкласса, как правило, не очень хорошая идея, особенно если вы просто игнорируете его (и только печатаете трассировку стека).Если вы не можете обработать исключение осмысленным образом, почему бы не позволить вызывающей стороне обработать его дальше по стеку?Я хотел бы рассмотреть вопрос о возвращении Optional<T> вместо null (что в любом случае является намерением Optional):

static <T> Optional<T> test(final T t) {
    final Service service = null;

    return Optional.ofNullable(t)
            .filter(p -> service.getAndValidate(p).test(p));

}

В качестве альтернативы, вы также можете выбрать выбрасывание значимого исключения (возможно, даже создать вашесобственный подкласс RuntimeException):

static <T> T test(final T t) {
    final Service service = null;

    return Optional.ofNullable(t)
            .filter(p -> service.getAndValidate(p).test(p))
            .orElseThrow(() -> new IllegalArgumentException("The validation was not successful"));

}
0 голосов
/ 24 июня 2019

В теле вашего метода вы переходите к map (лямбда в вашем примере), вы можете добавить блок try-catch вокруг вашего кода, как и в любом другом методе.

ЦельorElseThrow метод Optional - просто вызвать исключение, если ваш Optional пуст.Метод, который вы передаете ему, должен создать объект исключения, который вы хотите сгенерировать (например, RuntimeException::new), и затем он будет сгенерирован.

...