Деякі люди намагаються переконати вас, що вам доведеться грати за правилами. Слухай, але чи ти слухаєшся, ти повинен вирішити сам залежно від твоєї ситуації. Реальність така: "ТРЕБА грати за правилами" (а не "Ви ПОВИННІ грати за правилами"). Тільки майте на увазі, що якщо ви не будете грати за правилами, це може мати наслідки.
Ситуація застосовується не тільки в ситуації Runnable
, але і з Java 8 також дуже часто в контексті потоків та інших місць, де були введені функціональні інтерфейси без можливості мати справу з перевіреними винятками. Наприклад, Consumer
, Supplier
, Function
, BiFunction
і так далі все було оголошено без засобів для боротьби з перевіряються винятками.
То які ситуації та варіанти? У наведеному нижче тексті Runnable
представлено будь-який функціональний інтерфейс, який не оголошує винятки або оголошує винятки, занадто обмежені для конкретного випадку використання.
- Ви
Runnable
десь самі заявили , і можете замінити Runnable
чимось іншим.
- Подумайте про заміну
Runnable
на Callable<Void>
. В основному те саме, але дозволено кидати винятки; і return null
зрештою повинен , що є легким роздратуванням.
- Подумайте про заміну
Runnable
вашим власним звичаєм, @FunctionalInterface
який може створити саме ті винятки, які ви хочете.
- Ви використовували API, і доступні альтернативи. Наприклад, деякі Java API перевантажені, тому ви можете використовувати їх
Callable<Void>
замість Runnable
.
- Ви використовували API, і альтернатив немає. У цьому випадку у вас все ще немає можливостей.
- Ви можете обернути виняток
RuntimeException
.
- Ви можете зламати виняток у RuntimeException, використовуючи непомічений привід.
Ви можете спробувати наступне. Це трохи зламати, але іноді хак - це те, що нам потрібно. Тому що, чи слід перевіряти чи не перевіряти виняток, це визначається типом, але фактично має визначатися ситуацією.
@FunctionalInterface
public interface ThrowingRunnable extends Runnable {
@Override
default void run() {
try {
tryRun();
} catch (final Throwable t) {
throwUnchecked(t);
}
}
private static <E extends RuntimeException> void throwUnchecked(Throwable t) {
throw (E) t;
}
void tryRun() throws Throwable;
}
Я віддаю перевагу цьому, new RuntimeException(t)
оскільки він має коротший слід стека.
Тепер ви можете зробити:
executorService.submit((ThrowingRunnable) () -> {throw new Exception()});
Застереження. Можливість виконувати неперевірені закиди таким чином може бути фактично вилучена в майбутніх версіях Java, коли інформація про загальний тип обробляється не тільки під час компіляції, але й під час виконання.