Einige Leute versuchen dich davon zu überzeugen, dass du dich an die Regeln halten musst. Hören Sie zu, aber ob Sie gehorchen, sollten Sie selbst entscheiden, abhängig von Ihrer Situation. Die Realität ist "Sie sollten nach den Regeln spielen" (nicht "Sie müssen nach den Regeln spielen"). Seien Sie sich nur bewusst, dass es Konsequenzen haben kann, wenn Sie sich nicht an die Regeln halten.
Die Situation gilt nicht nur in der Situation von Runnable
, sondern mit Java 8 auch sehr häufig im Zusammenhang mit Streams und anderen Orten, an denen funktionale Schnittstellen eingeführt wurden, ohne die Möglichkeit, geprüfte Ausnahmen zu behandeln. Zum Beispiel Consumer
, Supplier
, Function
, BiFunction
und haben so auf alle ohne Einrichtungen erklärt mit geprüften Ausnahmen zu behandeln.
Was sind die Situationen und Optionen? Im folgenden Text Runnable
steht er für jede Funktionsschnittstelle, die keine Ausnahmen deklariert oder Ausnahmen für den jeweiligen Anwendungsfall zu eingeschränkt deklariert.
- Sie haben
Runnable
selbst irgendwo deklariert und könnten durch Runnable
etwas anderes ersetzen .
- Betrachten Sie ersetzen
Runnable
mit Callable<Void>
. Grundsätzlich das Gleiche, darf aber Ausnahmen werfen; und muss return null
am Ende, was ein leichter Ärger ist.
- Erwägen Sie,
Runnable
durch Ihre eigene Gewohnheit zu ersetzen @FunctionalInterface
, die genau die gewünschten Ausnahmen auslösen kann.
- Sie haben eine API verwendet und es stehen Alternativen zur Verfügung. Beispielsweise sind einige Java-APIs überladen, sodass Sie
Callable<Void>
stattdessen verwenden können Runnable
.
- Sie haben eine API verwendet und es gibt keine Alternativen. In diesem Fall stehen Ihnen immer noch keine Optionen zur Verfügung.
- Sie können die Ausnahme einschließen
RuntimeException
.
- Sie können die Ausnahme in eine RuntimeException hacken, indem Sie eine nicht aktivierte Besetzung verwenden.
Sie können Folgendes versuchen. Es ist ein bisschen ein Hack, aber manchmal ist ein Hack das, was wir brauchen. Denn ob eine Ausnahme aktiviert oder deaktiviert werden soll, hängt von ihrem Typ ab, sollte aber praktisch von der Situation abhängen.
@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;
}
Ich bevorzuge dies, new RuntimeException(t)
weil es eine kürzere Stapelspur hat.
Sie können jetzt tun:
executorService.submit((ThrowingRunnable) () -> {throw new Exception()});
Haftungsausschluss: Die Möglichkeit, ungeprüfte Casts auf diese Weise durchzuführen, wird in zukünftigen Java-Versionen möglicherweise tatsächlich entfernt, wenn Informationen zum Generika-Typ nicht nur zur Kompilierungszeit, sondern auch zur Laufzeit verarbeitet werden.