2015-07-26 4 views
5

Учитывая это Java 8 кодаметательное исключение из лямбда

public Server send(String message) { 
    sessions.parallelStream() 
     .map(Session::getBasicRemote) 
     .forEach(basic -> { 
      try { 
      basic.sendText(message); 
      } catch (IOException e) { 
      e.printStackTrace(); 
      } 
     }); 

    return this; 
} 

как мы правильно сделать это IOException быть делегировано стек вызов метода? (В двух словах, как сделать этот метод бросить эту IOException?)

Лямбда в Java не выглядит очень дружественной к обработке ошибок ...

ответ

8

Мой подход был бы украдкой брось от лямбда, но будьте осторожны, чтобы иметь метод send объявить его в пункте throws. Использование Exceptional класса I posted here:

public Server send(String message) throws IOException { 
    sessions.parallelStream() 
      .map(Session::getBasicRemote) 
      .forEach(basic -> Exceptional.from(() -> basic.sendText(message)).get()); 
    return this; 
} 

Таким образом, вы эффективно делает компилятор «Отвернись» для только немного, отключив его исключение проверки в одном месте в коде, но, объявив исключение на ваш send метод, вы восстанавливаете регулярное поведение для всех своих вызывающих абонентов.

+1

О, теперь мне это нравится. Это действительно очень подлый. –

2

Проблема заключается в том, действительно, что все @FunctionalInterface s, используемом в лямбды не допускают исключения быть выброшенным, за исключением исключенных исключений.

Одно решение использует a package of mine; с ним, ваш код может читать:

sessions.parallelStream() 
    .map(Session::getBasicRemote) 
    .forEach(Throwing.consumer(basic -> basic.sendText(message))); 
return this; 
+0

Как это позволяет 'send' выдавать исключение? –

+0

@MarkoTopolnik: Я так понимаю. Но ** много ** требуется больше работы, чтобы затем сделать 'send' throw' IOException'. Если я не ошибаюсь, вам в основном нужно поймать 'ThrownByLambdaException', а затем иметь серию' instanceof', чтобы выяснить, каково фактическое исключение, чтобы вы могли его перестроить. Может быть, это не так плохо для одного или двух исключений, но все же довольно многословный. –

+0

@ T.J.Crowder Чтобы оставаться справедливым для нашего коллеги fge (и, как вы обнаружили в нашем чате), 'throwing-lambdas' действительно поддерживает скрытую метательную идиому. –

5

I wrote an extension API Stream, который позволяет проверять исключение, которое должно быть выбрано.

public Server send(String message) throws IOException { 
    ThrowingStream.of(sessions, IOException.class) 
     .parallelStream() 
     .map(Session::getBasicRemote) 
     .forEach(basic -> basic.sendText(message)); 

    return this; 
} 
+0

спасибо, теперь это действительно хороший интерфейс :) обязательно проверит ваш исходный код – vach