2017-10-18 6 views
2

私は(いくつかのより多くのネストされたforEach'sstreamsで)いくつかのコードを持っている:ブロック外でforeachのコンシューマからRuntimeExceptionをキャッチする方法はありますか?

void process() throws RuntimeException 
{ 
    try { 

     ArrayList<Integer> ints = new ArrayList<>(); 
     ints.add(1); 
     ints.add(2); 
     ints.add(3); 

     ints.forEach(e -> { 

      System.out.println(e); 
      throw new RuntimeException("RuntimeException"); 

     }); 
    } 
    catch (RuntimeException rex) 
    { 
     rex.printStackTrace(); 
     throw rex; // throw it up, and up, and up... 
    } 
} 

foreach'sConsumer'saccept()は、デフォルトでは、例外をスローしませんので、それは動作しません。もしそれがthrowsの署名を持っていたとしても、私はブロックの外にそれを捕まえることができませんでした。

私がする必要があるのは、foreach()メソッド自体から例外をキャッチすることです。

は、私はその

void handleException(RuntimeException ex){ ... }

、すべてのforEach()'sのtry/catchでそれを呼び出すようないくつかの外部メソッドずに達成できる方法はありますか?

+0

あなたはあなたの実際のコードを表示する必要があり、これは設計上の問題のように聞こえます。 – Kayaman

+0

例外をスローする[Java 8 Lambda関数]の複製がありますか?(https://stackoverflow.com/questions/18198176/java-8-lambda-function-that-throws-exception) –

+1

このコードは 'RuntimeException' – Jerry06

答えて

2

質問が間違っていることがわかりました。実際にはRuntimeExceptionで動作します。チェック例外のために

が動作するコードです:

package Exporter; 

import java.util.function.Consumer; 
import java.util.function.Function; 

public final class LambdaExceptions { 

    @FunctionalInterface 
    public interface Consumer_WithExceptions<T, E extends Exception> { 
     void accept(T t) throws E; 
    } 

    @FunctionalInterface 
    public interface Function_WithExceptions<T, R, E extends Exception> { 
     R apply(T t) throws E; 
    } 

    /** 
    * .forEach(rethrowConsumer(name -> System.out.println(Class.forName(name)))); 
    */ 
    public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) throws E { 
     return t -> { 
      try { 
       consumer.accept(t); 
      } catch (Exception exception) { 
       throwActualException(exception); 
      } 
     }; 
    } 

    /** 
    * .map(rethrowFunction(name -> Class.forName(name))) or .map(rethrowFunction(Class::forName)) 
    */ 
    public static <T, R, E extends Exception> Function<T, R> rethrowFunction(Function_WithExceptions<T, R, E> function) throws E { 
     return t -> { 
      try { 
       return function.apply(t); 
      } catch (Exception exception) { 
       throwActualException(exception); 
       return null; 
      } 
     }; 
    } 

    @SuppressWarnings("unchecked") 
    private static <E extends Exception> void throwActualException(Exception exception) throws E { 
     throw (E) exception; 
    } 

} 

そして、それは魔法のように動作します:

void process() throws RuntimeException 
{ 
    try { 
     ArrayList<Integer> ints = new ArrayList<>(); 
     ints.add(1); 
     ints.add(2); 
     ints.add(3); 

     ints.forEach(LambdaExceptions.rethrowConsumer(e -> { 
      System.out.println(e); 
      throw new RuntimeException("RuntimeException"); 
     })); 

    } 
    catch (RuntimeException rex) 
    { 
     System.out.println("Got first exception"); 
     rex.printStackTrace(); 
     throw rex; 
    } 
} 
+0

それは動作しますが、あなたのプログラムの恐ろしいデザイン上の欠陥を隠しますか? – Kayaman

+1

私は使用するAPIの恐ろしいデザインをマークします。メインの投稿に対するあなたのコメントに答えるために、私はこのような回避策を講じなければならない理由は、外部企業から提供されたAPIが各データフェッチ要求でRuntimeExを投げるということです。たとえば、フォルダを取得するメソッド、サブフォルダなどのメソッドをネストした場合、このメソッドの内部で何かがうまくいかない場合は、タスク全体をロールバックする必要があります。 –

+0

よろしく。 – Kayaman

関連する問題