2016-04-14 3 views
6

Я использую Java 8 Stream API, и, как мы знаем, он не поддерживает проверенные исключения внутри любого функционального интерфейса внутри java.util.function.Является ли это хорошим решением для использования проверенной функции декоратора в Stream API?

я обычно должен использовать метод с проверяемыми исключениями внутри операций потоков, и я написал CheckedFunction декоратор использовать в этих операциях:

import java.util.function.BiFunction; 
import java.util.function.Function; 

public interface CheckedFunction<T, R, E extends Throwable> { 

    R apply(T t) throws E; 

    static <T, R, CE extends Throwable, UCE extends RuntimeException> Function<T, R> checked(
      CheckedFunction<T, R, CE> checked, Function<CE, UCE> exceptionHandler) { 
     return (t) -> { 
      try { 
       return checked.apply(t); 
      } 
      catch (RuntimeException | Error e) { 
       throw e; 
      } 
      catch (Throwable e) { 
       // can't catch - compiler error 
       if (e instanceof InterruptedException) { 
        Thread.currentThread().interrupt(); 
       } 
       throw exceptionHandler.apply((CE) e); 
      } 
     }; 
    } 
} 

так что я могу использовать его в таких случаях:

entities.stream() 
     .map(checked((entity) -> someResultChecked(entity), // throws IOException 
        (entity, e) -> { // e is of type IOException 
         log.error("exception during checked method of " + entity, e); 
         return new UncheckedIOException(e); 
        })) 
     .map(checked((entity) -> saveToDb(entity), // throws SQLException 
        (entity, e) -> { // e is of type SQLException 
         log.error("exception during saving " + entity, e); 
         return new UncheckedSQLException(e); 
        })) 
     .map(checked((entity) -> manyExceptionMethod(entity), // throws IOException, SQLException 
        (entity, e) -> { // e is of type Throwable 
         return new RuntimeException(e); 
        })) 

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

Это хорошая идея, или я могу столкнуться с скрытыми препятствиями?

ОБНОВЛЕНО: Повторное использование RuntimeException.

Кроме того, я нашел более четкое решение в jOOL с обработкой InterruptedException, которые могут привести к несовместимым поведение, если будут проигнорированы: https://github.com/jOOQ/jOOL/blob/master/src/main/java/org/jooq/lambda/Unchecked.java

+1

Вы должны взглянуть на JavaRx, которая обеспечивает хороший API для потоковой передачи с обработкой ошибок – flakes

+0

Спасибо, я попытался заглянуть в несколько раз, но всегда давал up.Maybe это сигнал, что мне нужно разобраться , – Monk3D

ответ

0

Вы получите ClassCastException если что-нибудь иное, чем IOException выкинут, так как вы улавливая все Throwable и передавая их в конструктор UncheckedIOException, который принимает только параметр IOException. Поскольку улавливание IOException в функциональном типе является такой общей потребностью, вместо того, чтобы пытаться обобщить его, может быть лучше всего держать его простым и сделать его только для этого проверенного исключения. Я бы предположил, что вам редко нужно дублировать код, чтобы сделать то же самое для других проверенных исключений.

@FunctionalInterface 
public interface CheckedIOFunction<T,R> { 

    R apply(T t) throws IOException; 

    static <T, R> Function<T, R> toUnchecked(CheckedIOFunction<T, R> function) { 
     return t -> { 
      try { 
       return function.apply(t); 
      } catch (IOException ioe) { 
       throw new UncheckedIOException(ioe); 
      } 
     }; 
    } 
} 
+1

Не совсем, информация о способе использования. Поэтому, если я буду использовать метод, который генерирует IOException, это будет , а в exceptionHandler вы получите e типа IOException, и если он выкинет что-нибудь еще, e будет иметь его тип (или типа Throwable, если есть несколько исключений). Например, вы можете запустить пример и посмотреть выход https://gist.github.com/gavlyukovskiy/30e28bae4b572b5a67c3a7c432069f46 – Monk3D

+0

Это интересная идея. Существуют ли какие-либо окончательные типы исключений, которые обычно возникают? –

+0

Обычно мы используем только одно исключение, поэтому его можно обрабатывать с помощью неконтролируемого аналога. Или мы часто бросаем UserApiException, чтобы указать проблему с запросом пользователя. – Monk3D

Смежные вопросы