В 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@FunctionalInterfaceinterface ThrowableRunnable { void run() throws Throwable;}// Assert a Throwable typestatic void assertThrows( Class<? extends Throwable> throwable, ThrowableRunnable runnable) { assertThrows(throwable, runnable, t -> {});}// Assert a Throwable type and implement more// assertions in a consumerstatic 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 exceptionsstatic void withExceptions( ThrowableRunnable runnable) { withExceptions(runnable, t -> {});}// This delegates exception handling to a consumerstatic 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 . |