Ich schätze die neuen Java 8-Funktionen für Lambdas und Standardmethoden-Schnittstellen sehr. Trotzdem langweilen mich geprüfte Ausnahmen. Wenn ich zum Beispiel nur alle sichtbaren Felder eines Objekts auflisten möchte, möchte ich einfach Folgendes schreiben:
Arrays.asList(p.getClass().getFields()).forEach(
f -> System.out.println(f.get(p))
);
Da die get
Methode jedoch möglicherweise eine aktivierte Ausnahme auslöst, die nicht mit dem Consumer
Schnittstellenvertrag übereinstimmt , muss ich diese Ausnahme abfangen und den folgenden Code schreiben:
Arrays.asList(p.getClass().getFields()).forEach(
f -> {
try {
System.out.println(f.get(p));
} catch (IllegalArgumentException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
);
In den meisten Fällen möchte ich jedoch nur, dass die Ausnahme als geworfen wird RuntimeException
und das Programm die Ausnahme ohne Kompilierungsfehler verarbeiten kann oder nicht.
Ich würde gerne Ihre Meinung zu meiner umstrittenen Problemumgehung für gestörte Ausnahmen erfahren. Zu diesem Zweck habe ich eine Hilfsschnittstelle ConsumerCheckException<T>
und eine Utility-Funktion rethrow
( aktualisiert gemäß dem Vorschlag von Dovals Kommentar ) wie folgt erstellt:
@FunctionalInterface
public interface ConsumerCheckException<T>{
void accept(T elem) throws Exception;
}
public class Wrappers {
public static <T> Consumer<T> rethrow(ConsumerCheckException<T> c) {
return elem -> {
try {
c.accept(elem);
} catch (Exception ex) {
/**
* within sneakyThrow() we cast to the parameterized type T.
* In this case that type is RuntimeException.
* At runtime, however, the generic types have been erased, so
* that there is no T type anymore to cast to, so the cast
* disappears.
*/
Wrappers.<RuntimeException>sneakyThrow(ex);
}
};
}
/**
* Reinier Zwitserloot who, as far as I know, had the first mention of this
* technique in 2009 on the java posse mailing list.
* http://www.mail-archive.com/javaposse@googlegroups.com/msg05984.html
*/
public static <T extends Throwable> T sneakyThrow(Throwable t) {
throw (T) t;
}
}
Und jetzt kann ich einfach schreiben:
Arrays.asList(p.getClass().getFields()).forEach(
rethrow(f -> System.out.println(f.get(p)))
);
Ich bin mir nicht sicher, ob dies die beste Redewendung ist, um die überprüften Ausnahmen umzukehren, aber wie ich erklärte, hätte ich gerne einen bequemeren Weg, um mein erstes Beispiel zu erreichen, ohne mit überprüften Ausnahmen umzugehen, und dies ist der einfachere Weg, den ich gefunden habe es zu tun.
sneakyThrow
inside of rethrow
auslösen, anstatt sie in a zu verpacken RuntimeException
. Alternativ können Sie auch die @SneakyThrows
Annotation von Project Lombok verwenden , die dasselbe tut.
Consumer
s in forEach
bei Verwendung von parallelen Stream
s parallel ausgeführt werden kann . Ein Throwable, der vom Withing des Verbrauchers ausgelöst wurde, wird dann an den aufrufenden Thread weitergegeben, was 1) die anderen gleichzeitig laufenden Verbraucher nicht anhält, was angemessen sein kann oder nicht, und 2) wenn mehr als einer der Verbraucher nur etwas auslöst Eines der Threads wird vom aufrufenden Thread gesehen.