Behandeln Sie Ausnahmen kühl mit Java 8-Lambda-Ausdrücken und der Stream-API

In der Java 8 Collection- und Stream-API ist Iteratable und in der for-Anweisung implementiert Sie können jetzt die Lambda-Formel für den Teil verwenden, den Sie berechnet haben.

Funktionale Schnittstellen wie Consumer sind jedoch nicht zum Auslösen von Ausnahmen definiert. Die Unfähigkeit, eine CheckedException (https://qiita.com/shunsuke227ono/items/142703c0b046f522f8bd) auszulösen, ist daher ein Nachteil des Lambda-Ausdrucks (https://teratail.com/questions/). 8461). Das Umschließen oder Zusammendrücken geprüfter Ausnahmen in Laufzeitausnahmen, die zur Kompilierungszeit nicht überprüft werden, ist aus Sicht der Ausnahmebehandlung nicht gut. ..

Qiita und Stackoverflow Auch i ku tsu / yoshi389111 / items / c6b7d373a00f8fd3d5f3) oder Eine Lösung wird angezeigt, aber [s: // //github.com/SeregaLBN/StreamUnthrower), das Lambda ist ein schlecht sichtbarer Code, [Schwere Implementierung für jede Funktionsschnittstelle](https://github.com/fge/throwing- lambdas / tree / master / src / main / java / com / github / fge / lambdas / konsumenten) oder nicht. Von Google Lehrer und alle sind besorgt / (´ω `;) \

Neu werfen durch Ergänzung der Laufzeitausnahme (ich möchte nicht)

Entpacken Sie die Laufzeit in CheckException. Ich möchte das nicht tun, weil der Code nicht sichtbar ist ...

try {
  Arrays.asList(1, 2, 3).forEach(e -> {
    try { 
      //Eine Geschäftslogik, die eine aktivierte Ausnahme auslöst
      methodTrowingIOException(e.intValue());
    } catch(IOException ex) {
      // throw new UncheckedIOException(ex);      
      throw new RuntimeException(ex);
    }
  }));
} catch (RuntimeException re) {
  Throwable e = re.getCause();//Check-Ausnahme auslösen
  throw e;
}

Sie können [UncheckedIOException] verwenden (https://docs.oracle.com/javase/jp/8/docs/api/java/io/UncheckedIOException.html), aber das Auspacken ist problematisch und RuntimeException wird verwendet. Es ist nicht viel anders als.

Definieren Sie ein FunctionalInterface mit einer Ausnahme in der throw-Klausel

@FunctionalInterface
public interface CheckedFunction<T, R> {
   R apply(T t) throws Exception;
}

void foo (CheckedFunction f) { ... }

Dies ist jedoch ein [für jeden](https: /), der [Verbraucher] voraussetzt (https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/Consumer.html). /docs.oracle.com/javase/jp/8/docs/api/java/lang/Iterable.html#forEach-java.util.function.Consumer-) usw., also abgelehnt.

Hinterhältiger Wurf Verwenden Sie Redewendungen, um geprüfte Ausnahmen zu behandeln

Sneaky throw ist ein Java-Compiler-Typprüfungsgeheimnis, das eine überprüfte Ausnahme zur Kompilierungszeit in eine RuntimeException überführt [Lombok]( Dies ist die unter https://qiita.com/opengl-8080/items/671ffd4bf84fe5e32557) verwendete Technik. Dieser Artikel ist detailliert.

@SuppressWarnings("unchecked")
@Nonnull
public static <E extends Throwable> void sneakyThrow(@Nonnull Throwable ex) throws E {
    throw (E) ex;
}

//Ich löse eine IOException, aber ich brauche keine Throws oder Catch, weil der Compiler mich zu einer RuntimeException verleitet, aber tatsächlich eine IOException auslöst
@Test(expected = IOException.class)
public void testSneakyThrow() {
    Throwing.sneakyThrow(new IOException());
}

Unter Anwendung dieser Redewendung definieren wir den folgenden Verbraucher.

import java.util.function.Consumer;

@FunctionalInterface
public interface ThrowingConsumer<T> extends Consumer<T> {

    @Override
    default void accept(final T e) {
        try {
            accept0(e);
        } catch (Throwable ex) {
            Throwing.sneakyThrow(ex);
        }
    }

    void accept0(T e) throws Throwable;
}

Gehen Sie bei der Verwendung wie folgt vor. Der obige Throwing Consumer, der die Consumer-Schnittstelle erbt, wird zum Empfangen des Lambda verwendet. Dies ist eine erweiterte Version von StackOverflow Answer.

    @Test
    public void testThrowingConsumer() throws IOException {
        thrown.expect(IOException.class);
        thrown.expectMessage("i=3");

        Arrays.asList(1, 2, 3).forEach((ThrowingConsumer<Integer>) e -> {
            int i = e.intValue();
            if (i == 3) {
                throw new IOException("i=" + i);
            }
        });
    }

Prägnantere Darstellung mit der statischen Methode Rethrow

Bei Throwing Consumer war der Teil, der den Lambda-Ausdruck für Each with Throwing Consumer erhält, etwas kompliziert auszudrücken. Ich möchte dies prägnanter gestalten.

public final class Throwing {

    private Throwing() {}

    @Nonnull
    public static <T> Consumer<T> rethrow(@Nonnull final ThrowingConsumer<T> consumer) {
        return consumer;
    }

    @SuppressWarnings("unchecked")
    @Nonnull
    public static <E extends Throwable> void sneakyThrow(@Nonnull Throwable ex) throws E {
        throw (E) ex;
    }
}

Wickeln Sie einfach den Lambda-Ausdruck mit der Rethrow-Methode ein. Dies ist meine bisherige endgültige Antwort.

Der Compiler geht davon aus, dass forEach nur eine Laufzeitausnahme ausgibt. Daher wird entweder IOException beim Aufrufer ausgelöst oder try / catch zum richtigen Zeitpunkt.

import static hivemall.utils.lambda.Throwing.rethrow;

    @Test
    public void testRethrow() throws IOException {
        thrown.expect(IOException.class);
        thrown.expectMessage("i=3");

        Arrays.asList(1, 2, 3).forEach(rethrow(e -> {
            int i = e.intValue();
            if (i == 3) {
                throw new IOException("i=" + i);
            }
        }));
    }

Bitte lassen Sie mich wissen, ob es einen besseren Weg gibt.

Recommended Posts

Behandeln Sie Ausnahmen kühl mit Java 8-Lambda-Ausdrücken und der Stream-API
Heutzutage Java Lambda Expressions und Stream API
So behandeln Sie Ausnahmen mit Java 8 Stream oder Optional kühl
[Für Anfänger] Über Lambda-Ausdrücke und Stream-API
Verwenden Sie Java-Lambda-Ausdrücke außerhalb der Stream-API
Java-Lambda-Ausdruck, der mit Comparator gelernt wurde
Behandeln Sie die Java 8-Datums- und Uhrzeit-API mit Thymeleaf mit Spring Boot
Überdenken von Entwurfsmustern mit Java8-Lambda-Ausdrücken und Stream - Builder-Muster -
Java Stream API
[Java] Json von der URL mit der Standard-API (javax.script) abrufen und verarbeiten
Java8 / 9-Anfänger: Streamen Sie API-Suchtpunkte und wie Sie damit umgehen
Interagieren Sie mit der LINE Message API mit Lambda (Java)
Verwendung der Java-API mit Lambda-Ausdrücken
[Java] Stream API / Map
Verstehen Sie Java 8 Lambda-Ausdrücke
Über Java-Lambda-Ausdrücke
Erläutern Sie Java 8-Lambda-Ausdrücke
[Inhouse-Lernsitzung] Java-Grundlagen - Lambda-Ausdruck und Stream-API - (13.07.2017)
Erste Schritte mit älteren Java-Ingenieuren (Stream + Lambda)
Verwenden Sie Lambda-Ebenen mit Java
Viel Spaß beim Programmieren mit Lambda-Stil und flüssiger Oberfläche
Java Stream API Spickzettel
Java Stream API in 5 Minuten
Java8-Stream, Zusammenfassung des Lambda-Ausdrucks
[Java] Einführung in den Lambda-Ausdruck
Erstellen Sie einen SlackBot mit AWS Lambda & API Gateway in Java
[Java] Stream API - Stream-Beendigungsverarbeitung
[Java] Stream API - Stream Zwischenverarbeitung
[Java] Einführung in die Stream-API
Konvertieren Sie ein zweidimensionales Array mit der Java 8 Stream-API in das CSV-Format
[Java] Stream API Zwischenoperation
[Java 8] Doppelte Löschung (& doppelte Überprüfung) mit Stream
Verwenden Sie Java mit MSYS und Cygwin
Verteilte Ablaufverfolgung mit OpenCensus und Java
Installieren Sie Java und Tomcat mit Ansible
[Einführung in Java] Über Lambda-Ausdrücke
[java8] Um die Stream-API zu verstehen
Java für Anfänger, Ausdrücke und Operatoren 1
Über Lambda, Stream, LocalDate von Java8
[Einführung in Java] Informationen zur Stream-API
Verwenden Sie JDBC mit Java und Scala.
[Java] Elementexistenzprüfung mit Stream
Java für Anfänger, Ausdrücke und Operatoren 2
PDF und TIFF mit Java 8 ausgeben
Ich habe versucht, die Java8 Stream API zu verwenden
Java 8 ~ Stream API ~ startet jetzt
Der Ursprung von Java-Lambda-Ausdrücken
Mit Java verschlüsseln und mit C # entschlüsseln
Verwendung von Java-Lambda-Ausdrücken
Java8-Listenkonvertierung mit Stream Map
[Salesforce] Registrieren und Aktualisieren statischer Ressourcen mit der Tooling-API (Java-Beispiel-SOAP-API)
Ich habe eine Lambda-Funktion in Java geschrieben und mit SAM bereitgestellt
Datenverarbeitung mit der Stream-API von Java 8
API-Integration von Java mit Jersey Client
Ich habe versucht, Java-Lambda-Ausdrücke zusammenzufassen
Versuchen Sie es mit der Stream-API in Java
Verknüpfen Sie Java- und C ++ - Code mit SWIG
Probieren wir WebSocket mit Java und Javascript aus!
[Java] Behandeln Sie Excel-Dateien mit Apache POI