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 / (´ω `;) \
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.
@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é.
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);
}
});
}
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