2016-01-19 3 views
0

Я пытаюсь создать действительно простой обратный вызов с использованием некоторых строк. Смысл кода IDE в том, что он просто стонет о непроверенном вызове. Может ли кто-нибудь дать мне исправить это? Идея в конце концов заключается в том, чтобы обернуть сетевой вызов, чтобы вернуть обещанный результат, и я могу прибегнуть к дополнительным функциям по мере необходимости.Обратный звонок с 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

Почему вы используете 'нового CompletableFuture () .supplyAsync' для вызова' static' метода? И почему вы не используете лямбда-выражения? – Holger

+0

Что вы хотите, чтобы вызов 'exclusively()' выполнялся? – thecoop

+0

* Редактировать * изменено на статичное, спасибо, что указали это, Хольгер. –

ответ

6

Прежде всего, ваш класс MakesANetworkCall реализует необработанный тип Supplier вместо Supplier<String>. Это позволит эффективно отключить проверку типов и скрыть все ошибки, сделанные вами, так что это не единственное предупреждение, вы должны беспокоиться о том, что это не единственное, что неправильно в вашем коде:

  • BiConsumer передается whenComplete должно быть способный потреблять Throwable в качестве второго аргумента.

  • Function, отправленный в exceptionally, должен потреблять Throwable и возвращает альтернативный результат.

Кроме того, вы вызываете метод static, используя выражение new CompletableFuture<String>() в качестве своей цели, и у вас есть выражение устаревшего создания строки в 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

Спасибо. Это моя первая попытка даже взглянуть на эту функциональность. Я отметил это правильно, потому что Хольгер попал туда первым, но с кивком в OldCurmudgeon –

0

CompletableFuture.exceptionally объявлен следующим образом:

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

Вы передавая ей Function<Exception, Exception>, в то время как вы должны передать его Function<Throwable, String>.

+0

Фактически, поскольку поставщик, опубликованный в вопросе, реализует необработанный тип «Поставщик», ошибки компилятора вообще отсутствуют. В противном случае 'whenComplete (новый BiConsumer () {...})' уже генерирует ошибку компилятора, поэтому тип последующего прикованного вызова неизвестен. 'New CompletableFuture ()', используемый для вызова 'static' метода' supplyAsync', не влияет на тип 'CompletableFuture' ... – Holger

+0

Я не сказал, что это ошибка компилятора - это предупреждение в моей среде IDE - - с изменениями выше я получаю «Непроверенный вызов в исключительном порядке (Функция ) в качестве члена исходного типа CompletableFuture« –

3

Основная проблема с class MakesANetworkCall implements Supplier {. Это использует необработанные типы и, следовательно, скрывает дополнительные проблемы. Fix, что class MakesANetworkCall implements Supplier<String> { и исправить все вытекающие проблемы, и вы получите:

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; 
       } 
      }); 
Смежные вопросы