Gérez les exceptions avec fraîcheur avec les expressions lambda Java 8 et l'API Stream

Dans Java 8 Collection and Stream API, Iteratable est implémenté, et dans l'instruction for Vous pouvez maintenant utiliser la formule lambda pour la pièce que vous étiez en train de calculer.

Cependant, les interfaces fonctionnelles telles que Consumer ne sont pas définies pour lever des exceptions. Ainsi, l'incapacité de lancer une CheckedException (https://qiita.com/shunsuke227ono/items/142703c0b046f522f8bd) est un inconvénient de l'expression lambda (https://teratail.com/questions/). 8461). Emballer ou compresser les exceptions vérifiées dans des exceptions d'exécution qui ne sont pas vérifiées au moment de la compilation n'est pas bon du point de vue de la gestion des exceptions. ..

Qiita et Stackoverflow Aussi i ku [tsu](https://qiita.com / yoshi389111 / items / c6b7d373a00f8fd3d5f3) ou Une solution est présentée, mais [Écraser l'exception: https. //github.com/SeregaLBN/StreamUnthrower), le lambda est un code peu visible, [Implémentation lourde pour chaque interface de fonction](https://github.com/fge/throwing- lambdas / tree / master / src / main / java / com / github / fge / lambdas / consumer) ou non. Par l'enseignant Google et tout le monde est inquiet / (´ω `;) \

Relancer en complétant l'exception d'exécution (je ne veux pas)

Déballer le Runtime dans CheckException. Je ne veux pas faire ça car le code est hors de vue ...

try {
  Arrays.asList(1, 2, 3).forEach(e -> {
    try { 
      //Une logique métier qui lève une exception vérifiée
      methodTrowingIOException(e.intValue());
    } catch(IOException ex) {
      // throw new UncheckedIOException(ex);      
      throw new RuntimeException(ex);
    }
  }));
} catch (RuntimeException re) {
  Throwable e = re.getCause();//Lancer une exception de vérification
  throw e;
}

Vous pouvez utiliser UncheckedIOException, mais le déballage est gênant et RuntimeException est utilisé. Ce n'est pas très différent de.

Définir une FunctionalInterface avec une exception dans la clause throws

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

void foo (CheckedFunction f) { ... }

Cependant, cela est basé sur Consumer [for Each](https: / /docs.oracle.com/javase/jp/8/docs/api/java/lang/Iterable.html#forEach-java.util.function.Consumer-) etc., donc rejeté.

Lancer sournois Utilisez des idiomes pour gérer les exceptions vérifiées

Sneaky throw est un secret de vérification de type du compilateur Java qui transforme une exception vérifiée en une RuntimeException au moment de la compilation [Lombok]( C'est la technique utilisée sur https://qiita.com/opengl-8080/items/671ffd4bf84fe5e32557). Cet article est détaillé.

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

//Je lance une IOException, mais je n'ai pas besoin de throws ou catch car le compilateur me trompe dans une RuntimeException, mais il lève en fait une IOException
@Test(expected = IOException.class)
public void testSneakyThrow() {
    Throwing.sneakyThrow(new IOException());
}

En appliquant cet idiome, nous définissons le consommateur suivant.

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;
}

Lors de son utilisation, procédez comme suit. Le Throwing Consumer ci-dessus, qui hérite de l'interface Consumer, est utilisé pour recevoir le lambda. Il s'agit d'une version avancée de 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);
            }
        });
    }

Représentation plus concise à l'aide de la méthode statique Rethrow

Avec Throwing Consumer, la partie qui reçoit l'expression lambda pour Each avec Throwing Consumer était un peu compliquée à exprimer. Je veux rendre cela plus concis.

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;
    }
}

Enveloppez simplement l'expression lambda avec la méthode rethrow. C'est ma réponse finale jusqu'à présent.

Le compilateur suppose que forEach ne vous donnera qu'une exception d'exécution, donc soit lance IOException à l'appelant, soit try / catch au bon moment.

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);
            }
        }));
    }

S'il vous plaît laissez-moi savoir s'il existe une meilleure façon.

Recommended Posts

Gérez les exceptions avec fraîcheur avec les expressions lambda Java 8 et l'API Stream
De nos jours, les expressions Java Lambda et l'API de flux
Comment gérer les exceptions froidement avec Java 8 Stream ou en option
[Pour les débutants] À propos des expressions lambda et de l'API Stream
Utiliser des expressions Java lambda en dehors de l'API Stream
Expression lambda Java apprise avec Comparator
Gérez l'API de date et d'heure Java 8 avec Thymeleaf avec Spring Boot
Repenser les modèles de conception avec les expressions lambda Java8 et Stream --Builder pattern -
API Java Stream
[Java] Obtenir et gérer Json à partir d'une URL avec une API standard (javax.script)
Java8 / 9 Beginners: Streaming API addiction points et comment les gérer
Interagir avec l'API de message LINE à l'aide de Lambda (Java)
Comment utiliser l'API Java avec des expressions lambda
[Java] API / carte de flux
Comprendre les expressions lambda Java 8
Pratique de l'API Java8 Stream
À propos des expressions Java lambda
Expliquer les expressions lambda Java 8
[Session d'étude interne] Principes de base de l'expression Java-Lambda et de l'API Stream- (13/07/2017)
Premiers pas avec les anciens ingénieurs Java (Stream + Lambda)
Utiliser des couches Lambda avec Java
Profitez de la programmation avec un style lambda et une interface fluide
Aide-mémoire de l'API Java Stream
API Java Stream en 5 minutes
Flux Java8, résumé de l'expression lambda
[Java] Introduction à l'expression lambda
Créer un SlackBot avec AWS lambda et API Gateway en Java
[Java] Stream API - Traitement de l'arrêt du flux
[Java] Stream API - Traitement intermédiaire de flux
[Java] Introduction à l'API Stream
Convertir un tableau bidimensionnel au format csv avec l'API Java 8 Stream
[Java] Opération intermédiaire de l'API Stream
[Java 8] Suppression en double (et vérification en double) avec Stream
Utiliser java avec MSYS et Cygwin
Traçage distribué avec OpenCensus et Java
Installez Java et Tomcat avec Ansible
[Introduction à Java] À propos des expressions lambda
[java8] Pour comprendre l'API Stream
Java pour les débutants, les expressions et les opérateurs 1
À propos de Lambda, Stream, LocalDate de Java8
[Introduction à Java] À propos de l'API Stream
Utilisez JDBC avec Java et Scala.
[Java] Vérification de l'existence des éléments avec Stream
Java pour les débutants, les expressions et les opérateurs 2
Sortie PDF et TIFF avec Java 8
J'ai essayé d'utiliser l'API Java8 Stream
Java 8 ~ Stream API ~ pour commencer maintenant
L'origine des expressions Java lambda
Crypter avec Java et décrypter avec C #
Comment utiliser les expressions Java lambda
Conversion de liste Java8 avec Stream map
[Salesforce] Enregistrement et mise à jour des ressources statiques avec l'API Tooling (exemple d'API SOAP Java)
J'ai écrit une fonction Lambda en Java et l'ai déployée avec SAM
Traitement des données à l'aide de l'API de flux de Java 8
Intégration API de Java avec Jersey Client
J'ai essayé de résumer les expressions Java lambda
Essayez d'utiliser l'API Stream en Java
Lier le code Java et C ++ avec SWIG
Essayons WebSocket avec Java et javascript!
[Java] Gérer les fichiers Excel avec Apache POI