2015-01-12 5 views
6

Con codice seguente,Come posso ripetere un'eccezione in un blocco lambda come dal blocco esterno?

void key(Key) throws SomeCheckedException { 
} 

void supplier(Supplier<Key> s) throws SomeCheckedException { 
    ofNullable(s).ifPresent(s -> {     // | 
     try {          // | 
      key(s.get());       // | 
     } catch (final SomeCheckedException sce) { // | 
      // sce is coming from key() method  // | 
      // How can I throw sce for outer method? // --/ 
     } 
    }); 
} 

Come posso buttare sce come se il metodo di metodo (supplier) sta gettando esso?

Si prega di notare che il codice sopra è solo un esempio. Ho bisogno che lo key(s.get()) sia all'interno di un'espressione lambda.

void supplier(Supplier<Key> s) throws SomeCheckException { 
    key(s.get()); 
} 
+2

Ah, non pensavo che quel tasto (...) 'possa lanciare l'eccezione controllata. Tuttavia [la mia risposta] (http://stackoverflow.com/a/27900544/2711488) gestisce anche quella causa. – Holger

risposta

2

Se si desidera elaborare eccezioni controllate in modo sicuro, è necessario un metodo di supporto che fornisca la possibilità di avvolgere l'eccezione in un sottotipo di RuntimeException. Ecco una tale funzione di supporto che utilizza la sicurezza tipo di generico per garantire che solo dichiarato eccezioni sarà nuovamente gettato (a meno che non si utilizza un operazione non sicura):

public static <E extends Throwable> void attempt(
    Consumer<Function<E,RuntimeException>> action) throws E { 

    final class CarryException extends RuntimeException { 
     final E carried; 
     CarryException(E cause) { 
      super(cause); 
      carried=cause; 
     } 
    } 

    try { action.accept(CarryException::new); } 
    catch(CarryException ex) { throw ex.carried; } 
} 

Supporta un arbitrario action che riceverà una funzione che fa il wrapping temporaneo del tipo di eccezione verificata su RuntimeException. Questo wrapping sarà trasparente, il metodo attempt si completerà normalmente o genererà l'eccezione originale verificata E (o un'eccezione non controllata non verificata se si verifica uno).

modo da poterlo utilizzare in questo modo:

public static void processIterm(Supplier<Key> s) 
    throws SomeCheckedException { 

    attempt((Function<SomeCheckedException, RuntimeException> thrower) -> 
     Optional.ofNullable(s).ifPresent(nonNull -> { 
      try { key(nonNull.get()); } // assuming key may throw SomeCheckedException 
      catch(SomeCheckedException e) { throw thrower.apply(e); } 
     })); 
} 

A causa delle operazioni nidificate il compilatore è in grado di dedurre il tipo automaticamente l'eccezione. Il codice sopra riportato utilizza una dichiarazione esplicita del tipo di parametro thrower. In alternativa puoi usare un richiamo del tipo del metodo helper come

ContainingClass.<SomeCheckedException>attempt(thrower -> 
    Optional.ofNullable(s).ifPresent(nonNull -> { 
     try { key(nonNull.get()); } 
     catch(SomeCheckedException e) { throw thrower.apply(e); } 
    })); 
7

Non è possibile. Supplier#get() non dichiara di lanciare alcuna eccezione (controllata). Ricorda che un'espressione lambda crea semplicemente un'istanza, in realtà non invoca il metodo dell'interfaccia funzionale di destinazione.

Se lo si desidera, è possibile avvolgere l'eccezione controllata in un'eccezione non controllata e lanciarla.