2016-01-19 46 views
0

我想用一些字符串創建一個非常簡單的回調函數。 IDE的代碼意義是呻吟聲異常未經檢查的調用。任何人都可以爲我解決這個問題嗎?這個想法最後是打包網絡調用,以便返回承諾的結果,並根據需要添加其他功能。Callback with CompletableFuture

import java.util.concurrent.*; 
import java.util.function.BiConsumer; 
import java.util.function.Function; 
import java.util.function.Supplier; 

public class FuturesTest { 

    public static void main(String[] args) throws Exception { 
     new FuturesTest().go(); 
    } 

    private void go() throws ExecutionException, InterruptedException { 
     CompletableFuture.supplyAsync(new MakesANetworkCall()) 
       .whenComplete(new BiConsumer<String, String>() { 
        @Override 
        public void accept(String result, String s) { 
         System.out.println(result.toString()); 
        } 
       }) 
       .exceptionally(new Function<Exception, Exception>() { 
            @Override 
            public Exception apply(Exception e) { 
             e.printStackTrace(); 
             return e; 
            } 
           } 
       ).thenApplyAsync(new Function<String, String>() { 
        @Override 
        public String apply(String o) { 
         System.out.println("Last action of all!"); 
         return null; 
        } 
       }); 

     System.out.println("Main thread will sleep"); 
     Thread.sleep(2500); 
     System.out.println("Program over"); 
    } 

    class MakesANetworkCall implements Supplier { 

     @Override 
     public String get() { 
      try { 
       System.out.println("Ground control to Major Tom"); 
       Thread.sleep(2000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
//   int i = 2/0; 
      return new String("Major Tom reporting!"); 
     } 
    } 
} 
+0

:修正了對class MakesANetworkCall implements Supplier<String> {和解決所有的問題隨之而來,你會得到?你爲什麼不使用lambda表達式? – Holger

+0

你想給''異常()'做什麼? – thecoop

+0

*編輯*更改爲靜態,謝謝指出,Holger。 –

回答

6

首先,您的類MakesANetworkCall執行原始類型Supplier而不是Supplier<String>。這將有效地禁用類型檢查和隱藏你讓所有的錯誤,所以它不是單一的警告,你應該擔心,因爲這是不是唯一的東西錯在你的代碼:

  • BiConsumer傳遞給whenComplete應能夠消耗Throwable作爲第二個參數。

  • 傳遞給exceptionallyFunction應消耗Throwable並返回替代結果。

此外,要調用使用作爲其靶的表達new CompletableFuture<String>()一個static方法和你有一個過時的字符串創建表達式作爲new String("Major Tom reporting!")其中簡單恆定"Major Tom reporting!"都行。一般來說,你似乎總是試圖使用一種不恰當的方法,即設計用來消耗你不使用的東西,或者用於提供你沒有的東西。考慮一下:

CompletableFuture.supplyAsync(new MakesANetworkCall()) 
    .thenAccept(result -> System.out.println(result)) 
    .exceptionally(e -> { e.printStackTrace(); return null;}) 
    .thenRun(()->System.out.println("Last action of all!")); 

這似乎是你的意圖。如果你確保你的MakesANetworkCall正確實現Supplier<String>,這應該編譯沒有任何警告。

+0

謝謝。這是我第一次嘗試這種功能。我已經標記了這個正確,因爲Holger先到達那裏,但是向OldCurmudgeon點頭 –

0

CompletableFuture.exceptionally聲明,像這樣:

public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn); 

你傳遞一個Function<Exception, Exception>,而你應該傳遞一個Function<Throwable, String>

+0

實際上,由於問題中發佈的供應商實現了原始類型「供應商」,因此根本沒有編譯器錯誤。否則,'whenComplete(new BiConsumer (){...})'已經生成編譯器錯誤,所以後續鏈接調用的類型是未知的。 'CompletableFuture ()'用於調用'static'方法'supplyAsync'對'CompletableFuture'類型沒有影響... – Holger

+0

我沒有說這是一個編譯器錯誤 - 這是我的IDE中的警告 - - 以上更改我得到「未經檢查的調用異常(功能)作爲原始類型CompletableFuture成員」 –

3

您的核心問題是class MakesANetworkCall implements Supplier {。這是使用原始類型,因此隱藏了更多的問題。你爲什麼要使用`新CompletableFuture ().supplyAsync`調用`static`方法

CompletableFuture.supplyAsync(new MakesANetworkCall()) 
      // Not <String, String> 
      .whenComplete(new BiConsumer<String, Throwable>() { 
       @Override 
       public void accept(String result, Throwable t) { 
        System.out.println(result); 
       } 
      }) 
      // Not <Exception,Exception> 
      .exceptionally(new Function<Throwable, String>() { 
       @Override 
       public String apply(Throwable t) { 
        t.printStackTrace(); 
        // Must return a Streing 
        return t.getMessage(); 
       } 
      } 
      ).thenApplyAsync(new Function<String, String>() { 
       @Override 
       public String apply(String o) { 
        System.out.println("Last action of all!"); 
        return null; 
       } 
      });