В Data Geekery мы любим Java. И так как мы действительно входим в свободный API jOOQ и запросы DSL , мы абсолютно взволнованы тем, что Java 8 принесет в нашу экосистему.
Ява 8 Пятница
Каждую пятницу мы показываем вам пару замечательных новых функций Java 8 в виде учебника, в которых используются лямбда-выражения, методы расширения и другие замечательные вещи. Вы найдете исходный код на GitHub .
Лучшие исключения
У меня возникла идея, когда я наткнулся на проблему # 706 JUnit GitHub , которая о предложении нового метода:
1
|
ExpectedException#expect(Throwable, Callable) |
Одним из предложений было создать перехватчик для исключений, подобных этому.
1
2
3
4
|
assertEquals(Exception. class , thrown(() -> foo()).getClass()); assertEquals( "yikes!" , thrown(() -> foo()).getMessage()); |
С другой стороны, почему бы просто не добавить что-то совершенно новое в соответствии с этим?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
// This is needed to allow for throwing Throwables // from lambda expressions @FunctionalInterface interface ThrowableRunnable { void run() throws Throwable; } // Assert a Throwable type static void assertThrows( Class<? extends Throwable> throwable, ThrowableRunnable runnable ) { assertThrows(throwable, runnable, t -> {}); } // Assert a Throwable type and implement more // assertions in a consumer static void assertThrows( Class<? extends Throwable> throwable, ThrowableRunnable runnable, Consumer<Throwable> exceptionConsumer ) { boolean fail = false ; try { runnable.run(); fail = true ; } catch (Throwable t) { if (!throwable.isInstance(t)) Assert.fail( "Bad exception type" ); exceptionConsumer.accept(t); } if (fail) Assert.fail( "No exception was thrown" ); } |
Таким образом, оба приведенных выше метода утверждают, что данный throwable генерируется из данного runnable — ThrowableRunnable
, потому что большинство функциональных интерфейсов, к сожалению, не позволяют генерировать проверенные исключения. Смотрите эту статью для деталей .
Теперь мы используем приведенный выше гипотетический JUnit API как таковой:
1
2
3
4
5
6
|
assertThrows(Exception. class , () -> { throw new Exception(); }); assertThrows(Exception. class , () -> { throw new Exception( "Message" ); }, e -> assertEquals( "Message" , e.getMessage())); |
На самом деле, мы могли бы даже пойти дальше и объявить исключительный вспомогательный метод, например:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
// This essentially swallows exceptions static void withExceptions( ThrowableRunnable runnable ) { withExceptions(runnable, t -> {}); } // This delegates exception handling to a consumer static void withExceptions( ThrowableRunnable runnable, Consumer<Throwable> exceptionConsumer ) { try { runnable.run(); } catch (Throwable t) { exceptionConsumer.accept(t); } } |
Это полезно, чтобы проглотить все виды исключений. Следующие две идиомы, таким образом, эквивалентны:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
try { // This will fail assertThrows(SQLException. class , () -> { throw new Exception(); }); } catch (Throwable t) { t.printStackTrace(); } withExceptions( // This will fail () -> assertThrows(SQLException. class , () -> { throw new Exception(); }), t -> t.printStackTrace() ); |
Очевидно, что эти идиомы не обязательно более полезны, чем фактический блок try .. catch .. finally
, особенно потому, что он не поддерживает правильную типизацию исключений (по крайней мере, в этом примере) и не поддерживает try-with заявление.
Тем не менее, такие полезные методы пригодятся время от времени.
Ссылка: | Java 8, пятница: лучшие исключения от нашего партнера по JCG Лукаса Эдера в блоге JAVA, SQL и AND JOOQ . |