2016-11-24 14 views
2

私はCompletableFutureを初めて使うので、例外をスローするMetadataLoginUtil :: loginメソッドを呼びたいと思います。しかし、私は '例外的に'書かれているが、以下のコードはコンパイルされていません。これは、try & catch内でMetadataLoginUtil :: login 'をラップする必要があると言います。try&catch on supplyAsync

お知らせください。 ありがとう!

public void run() throws ConnectionException { 
     CompletableFuture<Void> mt = CompletableFuture.supplyAsync(MetadataLoginUtil::login).exceptionally(e -> {System.out.println(e); return null; }).thenAccept(e -> System.out.println(e)); 
} 

答えて

1

CompletableFuture.supplyAsync(Supplier<U>)java.util.function.Supplier<U>インスタンスを期待し、Supplier.get()メソッドのシグネチャは、チェック例外を許可しません。これを明確に見るには、CompletableFuture.supplyAsync(MetadataLoginUtil::login)は、

CompletableFuture<Void> mt = CompletableFuture.supplyAsync(new Supplier<Void>() { 
     @Override 
     public Void get() { 
      return MetadataLoginUtil.login(); 
     } 
    }) 

と明らかにコンパイルできないことに注意してください。

あなたはそれはかなりありませんが、CompletableFutureのAPIは非常によくチェック例外では動作していないようCompletableFuture.supplyAsync(MetadataLoginUtil::login).exceptionally(e -> {System.out.println(e); return null; })

CompletableFuture.supplyAsync(() -> { 
     try { 
      return MetadataLoginUtil.login(); 
     } catch (Exception e) { 
      System.out.println(e); 
      return null; 
     } 
    }) 

を変え、あなたのSupplier内の例外を処理することができます。

+1

ありがとうございます。「例外的に」というのはどういう点ですか?私はなぜこれが必要なのか分かりません – sfdcdev

+0

問題はむしろ、完全なラムダ原理はチェック例外をまったくカバーしないということです。それでも、例外的に使用するか、RuntimeExceptionsとその派生クラスを処理できます。 1つの非常に一般的なパターンは、実行時の例外でラムダの例外をラップして再スローすることです:... catch(Exception e){throw new RuntimeException(e); } – mtj

+1

@mtj:ラムダと例外は一緒に動作します。インタフェースがどのように宣言されているかだけの問題です。あなたは、たとえ提供された関数の引数が投げることができるものを正確に投げ出すメソッドを宣言するために、例外の型をインタフェースの型パラメータにすることさえできます。しかし、これは、APIが修正された初期のJava 8コンパイラー・バージョンでは機能しませんでした。 – Holger

5

これは、CompletableFutureが一般的にどのように機能するのか不便ではありませんが、すべてがチェック例外を許可しない機能インターフェイスを使用しています。これは、基本的には、元のsupplyAsyncと同じようにやってますが、チェック例外を許可され

public static <T> CompletableFuture<T> supplyAsync(Callable<T> c) { 
    CompletableFuture<T> f=new CompletableFuture<>(); 
    CompletableFuture.runAsync(() -> { 
     try { f.complete(c.call()); } catch(Throwable t) { f.completeExceptionally(t); } 
    }); 
    return f; 
} 

:あなたは、代替 supplyAsyncの方法でこれを解決することができます。したがって、最初の試みのように使用して、最初の supplyAsyncコールをリダイレクトするだけです。

CompletableFuture<Void> mt = supplyAsync(MetadataLoginUtil::login) 
    .exceptionally(e -> { System.out.println(e); return null; }) 
    .thenAccept(e -> System.out.println(e));