2016-04-14 8 views
6

Używam Java 8 Stream API, a jak wiemy, nie obsługuje sprawdzonych wyjątków wewnątrz dowolnego funkcjonalnego interfejsu wewnątrz java.util.function.Czy warto zastosować funkcję sprawdzania dekoratorów w Stream API?

Zazwyczaj trzeba użyć metody z zaznaczonych wyjątków wewnątrz operacji strumieni, a ja napisałem CheckedFunction dekorator używać wewnątrz tych operacji:

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); 
      } 
     }; 
    } 
} 

więc można go używać w takich przypadkach:

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); 
        })) 

Zawinie każdy zaznaczony wyjątek w niezaznaczonym, ale wiem, że jeśli metoda wyrzuci więcej niż jeden wyjątek, to zostanie wymazany na Throwable, użyję go w prostych przypadkach.

Czy to dobry pomysł, czy mogę napotkać ukryte przeszkody?

ZAKTUALIZACJA: Rethrowing RuntimeExceptions.

Również znalazłem bardziej jasne rozwiązanie w JOOL z obsługą InterruptedException który może powodować niespójne zachowanie jeśli będą ignorowane: https://github.com/jOOQ/jOOL/blob/master/src/main/java/org/jooq/lambda/Unchecked.java

+1

Należy przyjrzeć JavaRx który zapewnia dobry API dla przesyłania strumieniowego z obsługi błędów – flakes

+0

Dzięki, starałem się spojrzeć na kilka razy, ale zawsze dało up.Maybe jest to sygnał, że trzeba rozwiązać to . – Monk3D

Odpowiedz

0

dostaniesz ClassCastException jeśli coś innego niż IOException zostanie wyrzucony, ponieważ jesteś przechwytywanie wszystkich Throwable i przekazywanie ich do konstruktora UncheckedIOException, który przyjmuje tylko IOException jako parametr. Ponieważ złapanie IOException w typie funkcjonalnym jest tak powszechną potrzebą, zamiast próbować uogólniać, może być najlepiej, aby było to proste i uczynić je tylko dla tego sprawdzonego wyjątku. Wyobrażam sobie, że rzadko trzeba duplikować kod, aby zrobić to samo dla innych sprawdzonych wyjątków.

@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

Niezupełnie, infers z metody, której używam. Więc jeśli użyję metody, która wyrzuca wyjątek IOException, to , a w wyjątkuHandler otrzymasz e typu wyjątek IOException, a jeśli będzie on cokolwiek wyrzucał e będzie jego typu (lub typu Throwable, jeśli będzie, wiele wyjątków). Na przykład możesz uruchomić przykład i zobaczyć wyjście https://gist.github.com/gavlyukovskiy/30e28bae4b572b5a67c3a7c432069f46 – Monk3D

+0

To interesujący pomysł. Czy są jakieś ostateczne typy wyjątków, które są zwykle zgłaszane? –

+0

Powszechnie używamy tylko jednego wyjątku, więc można go obsłużyć przy pomocy niesprawdzonego analogu. Lub często rzucamy UserApiException, aby wskazać problem z żądaniem użytkownika. – Monk3D

Powiązane problemy