Je sais comment créer une référence à une méthode qui a un paramètre String
et retourne une int
, c'est:
Function<String, Integer>
Cependant, cela ne fonctionne pas si la fonction lève une exception, par exemple, elle est définie comme suit:
Integer myMethod(String s) throws IOException
Comment définirais-je cette référence?
Vous devrez faire l'une des choses suivantes.
Si c'est votre code, alors définissez votre propre interface fonctionnelle qui déclare l'exception vérifiée
@FunctionalInterface
public interface CheckedFunction<T, R> {
R apply(T t) throws IOException;
}
et l'utiliser
void foo (CheckedFunction f) { ... }
Sinon, encapsulez Integer myMethod(String s)
dans une méthode qui ne déclare pas une exception vérifiée:
public Integer myWrappedMethod(String s) {
try {
return myMethod(s);
}
catch(IOException e) {
throw new UncheckedIOException(e);
}
}
et alors
Function<String, Integer> f = (String t) -> myWrappedMethod(t);
ou
Function<String, Integer> f =
(String t) -> {
try {
return myMethod(t);
}
catch(IOException e) {
throw new UncheckedIOException(e);
}
};
Vous pouvez réellement étendre Consumer
(et Function
etc.) avec une nouvelle interface qui gère les exceptions - en utilisant les méthodes default de Java 8!
Considérez cette interface (étend Consumer
):
@FunctionalInterface
public interface ThrowingConsumer<T> extends Consumer<T> {
@Override
default void accept(final T elem) {
try {
acceptThrows(elem);
} catch (final Exception e) {
// Implement your own exception handling logic here..
// For example:
System.out.println("handling an exception...");
// Or ...
throw new RuntimeException(e);
}
}
void acceptThrows(T elem) throws Exception;
}
Ensuite, par exemple, si vous avez une liste:
final List<String> list = Arrays.asList("A", "B", "C");
Si vous voulez le consommer (par exemple avec forEach
) avec du code qui lève des exceptions, vous auriez traditionnellement mis en place un bloc try/catch:
final Consumer<String> consumer = aps -> {
try {
// maybe some other code here...
throw new Exception("asdas");
} catch (final Exception ex) {
System.out.println("handling an exception...");
}
};
list.forEach(consumer);
Mais avec cette nouvelle interface, vous pouvez l'instancier avec une expression lambda et le compilateur ne se plaindra pas:
final ThrowingConsumer<String> throwingConsumer = aps -> {
// maybe some other code here...
throw new Exception("asdas");
};
list.forEach(throwingConsumer);
Ou même simplement le lancer pour être plus succinct!:
list.forEach((ThrowingConsumer<String>) aps -> {
// maybe some other code here...
throw new Exception("asda");
});
Update: Il semble y avoir une très jolie bibliothèque d’utilitaires dans Durian appelée Errors qui peut être utilisée pour résoudre ce problème avec beaucoup plus de souplesse. Par exemple, dans mon implémentation ci-dessus, j'ai explicitement défini la stratégie de traitement des erreurs (System.out...
ou throw RuntimeException
), alors que les erreurs de Durian vous permettent d'appliquer une stratégie à la volée via une vaste suite de méthodes utilitaires. Merci pour le partage , @NedTwigg !.
Exemple d'utilisation:
list.forEach(Errors.rethrow().wrap(c -> somethingThatThrows(c)));
Je pense que la classe Errors
de Durian combine plusieurs des avantages des diverses suggestions ci-dessus.
Pour inclure Durian dans votre projet, vous pouvez soit:
com.diffplug.durian:durian:3.3.0
Throwing.Java
et Errors.Java
Ceci n’est pas spécifique à Java 8. Vous essayez de compiler quelque chose d’équivalent à:
interface I {
void m();
}
class C implements I {
public void m() throws Exception {} //can't compile
}
Avertissement: je n'ai pas encore utilisé Java 8, seulement lu à ce sujet.
Function<String, Integer>
ne lance pas IOException
, vous ne pouvez donc y insérer aucun code aussi throws IOException
. Si vous appelez une méthode qui attend un Function<String, Integer>
, le lambda que vous lui transmettez ne peut pas lancer IOException
, point. Vous pouvez soit écrire un lambda comme ceci (je pense que c'est la syntaxe lambda, pas sûr):
(String s) -> {
try {
return myMethod(s);
} catch (IOException ex) {
throw new RuntimeException(ex);
// (Or do something else with it...)
}
}
Ou, si la méthode à laquelle vous transmettez le lambda est celle que vous avez écrite vous-même, vous pouvez définir une nouvelle interface fonctionnelle et l'utiliser comme type de paramètre au lieu de Function<String, Integer>
:
public interface FunctionThatThrowsIOException<I, O> {
O apply(I input) throws IOException;
}
Si cela ne vous dérange pas d'utiliser une librairie tierce ( Vavr ), vous pouvez écrire
CheckedFunction1<String, Integer> f = this::myMethod;
Il possède également la prétendue monade Try qui gère les erreurs:
Try(() -> f.apply("test")) // results in a Success(Integer) or Failure(Throwable)
.map(i -> ...) // only executed on Success
...
S'il vous plaît lire plus ici .
Disclaimer: Je suis le créateur de Vavr.
Vous pouvez utiliser unthrow wrapper
Function<String, Integer> func1 = s -> Unthrow.wrap(() -> myMethod(s));
ou
Function<String, Integer> func2 = s1 -> Unthrow.wrap((s2) -> myMethod(s2), s1);
Vous pouvez.
Etendre la UtilException
de @marcg et ajouter le <E extends Exception>
générique si nécessaire: le compilateur vous obligera de nouveau à ajouter des clauses throw et tout se passe comme si vous pouviez lancer des exceptions vérifiées de manière native sur les flux Java 8.
public final class LambdaExceptionUtil {
@FunctionalInterface
public interface Function_WithExceptions<T, R, E extends Exception> {
R apply(T t) throws E;
}
/**
* .map(rethrowFunction(name -> Class.forName(name))) or .map(rethrowFunction(Class::forName))
*/
public static <T, R, E extends Exception> Function<T, R> rethrowFunction(Function_WithExceptions<T, R, E> function) throws E {
return t -> {
try {
return function.apply(t);
} catch (Exception exception) {
throwActualException(exception);
return null;
}
};
}
@SuppressWarnings("unchecked")
private static <E extends Exception> void throwActualException(Exception exception) throws E {
throw (E) exception;
}
}
public class LambdaExceptionUtilTest {
@Test
public void testFunction() throws MyTestException {
List<Integer> sizes = Stream.of("ciao", "hello").<Integer>map(rethrowFunction(s -> transform(s))).collect(toList());
assertEquals(2, sizes.size());
assertEquals(4, sizes.get(0).intValue());
assertEquals(5, sizes.get(1).intValue());
}
private Integer transform(String value) throws MyTestException {
if(value==null) {
throw new MyTestException();
}
return value.length();
}
private static class MyTestException extends Exception { }
}
Ce problème me préoccupe également; c'est pourquoi j'ai créé ce projet .
Avec cela, vous pouvez faire:
final ThrowingFunction<String, Integer> f = yourMethodReferenceHere;
Il existe un total de 39 interfaces définies par le JDK qui ont un tel équivalent Throwing
; Ce sont tous des @FunctionalInterface
s utilisés dans les flux (Stream
de base, mais aussi IntStream
, LongStream
et DoubleStream
).
Et comme chacun d'eux étend sa contrepartie non lanceuse, vous pouvez également les utiliser directement dans lambdas:
myStringStream.map(f) // <-- works
Le comportement par défaut est que lorsque votre jeté lambda lève une exception vérifiée, une ThrownByLambdaException
est levée avec l'exception vérifiée comme cause. Vous pouvez donc capturer cela et en connaître la cause.
D'autres fonctionnalités sont également disponibles.
Vous pouvez cependant créer votre propre FunctionalInterface qui se présente comme ci-dessous.
@FunctionalInterface
public interface UseInstance<T, X extends Throwable> {
void accept(T instance) throws X;
}
puis implémentez-le en utilisant Lambdas ou des références comme indiqué ci-dessous.
import Java.io.FileWriter;
import Java.io.IOException;
//lambda expressions and the execute around method (EAM) pattern to
//manage resources
public class FileWriterEAM {
private final FileWriter writer;
private FileWriterEAM(final String fileName) throws IOException {
writer = new FileWriter(fileName);
}
private void close() throws IOException {
System.out.println("close called automatically...");
writer.close();
}
public void writeStuff(final String message) throws IOException {
writer.write(message);
}
//...
public static void use(final String fileName, final UseInstance<FileWriterEAM, IOException> block) throws IOException {
final FileWriterEAM writerEAM = new FileWriterEAM(fileName);
try {
block.accept(writerEAM);
} finally {
writerEAM.close();
}
}
public static void main(final String[] args) throws IOException {
FileWriterEAM.use("eam.txt", writerEAM -> writerEAM.writeStuff("sweet"));
FileWriterEAM.use("eam2.txt", writerEAM -> {
writerEAM.writeStuff("how");
writerEAM.writeStuff("sweet");
});
FileWriterEAM.use("eam3.txt", FileWriterEAM::writeIt);
}
void writeIt() throws IOException{
this.writeStuff("How ");
this.writeStuff("sweet ");
this.writeStuff("it is");
}
}
Idiotisme de lancer sournois permet de contourner CheckedException
de l'expression Lambda. Le fait d'insérer une CheckedException
dans une RuntimeException
n'est pas bon pour la gestion d'erreur stricte.
Il peut être utilisé comme une fonction Consumer
utilisée dans une collection Java.
Voici une version simple et améliorée de la réponse de jib .
import static Throwing.rethrow;
@Test
public void testRethrow() {
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);
}
}));
}
Cela enveloppe le lambda dans un rethrow. CheckedException
rediffuse toute Exception
qui a été jetée dans votre lambda.
public final class Throwing {
private Throwing() {}
@Nonnull
public static <T> Consumer<T> rethrow(@Nonnull final ThrowingConsumer<T> consumer) {
return consumer;
}
/**
* The compiler sees the signature with the throws T inferred to a RuntimeException type, so it
* allows the unchecked exception to propagate.
*
* http://www.baeldung.com/Java-sneaky-throws
*/
@SuppressWarnings("unchecked")
@Nonnull
public static <E extends Throwable> void sneakyThrow(@Nonnull Throwable ex) throws E {
throw (E) ex;
}
}
Trouvez un code complet et des tests unitaires ici .
J'ai eu ce problème avec Class.forName et Class.newInstance dans un lambda, alors je viens de le faire:
public Object uncheckedNewInstanceForName (String name) {
try {
return Class.forName(name).newInstance();
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
À l'intérieur du lambda, au lieu d'appeler Class.forName ("myClass"). NewInstance () Je viens d'appeler uncheckedNewInstanceForName ("myClass")
Il y a beaucoup d'excellentes réponses déjà publiées ici. Juste essayer de résoudre le problème avec une perspective différente. C'est juste mes 2 cents, corrigez-moi s'il vous plaît si je me trompe quelque part.
La clause Throws dans FunctionalInterface n'est pas une bonne idée
Je pense que ce n'est probablement pas une bonne idée d'appliquer des exceptions IOException pour les raisons suivantes
Cela me semble un anti-motif pour Stream/Lambda. L'idée est que l'appelant décide du code à fournir et de la gestion de l'exception. Dans de nombreux scénarios, l'exception IOException peut ne pas être applicable pour le client. Par exemple, si le client obtient une valeur de la mémoire cache/mémoire au lieu d'effectuer des E/S réelles.
En outre, la gestion des exceptions dans les flux devient vraiment hideuse. Par exemple, voici mon code ressemblera si j'utilise votre API
acceptMyMethod(s -> {
try {
Integer i = doSomeOperation(s);
return i;
} catch (IOException e) {
// try catch block because of throws clause
// in functional method, even though doSomeOperation
// might not be throwing any exception at all.
e.printStackTrace();
}
return null;
});
Moche n'est-ce pas? De plus, comme je l’ai mentionné dans mon premier point, la méthode doSomeOperation peut ou non renvoyer une exception IOException (selon l’implémentation du client/appelant), mais en raison de la clause throws de votre méthode FunctionalInterface, je dois toujours écrire le essayer-attraper.
Que dois-je faire si je sais vraiment que cette API génère une exception IOException
Nous confondons donc probablement FunctionalInterface avec des interfaces typiques. Si vous savez que cette API lève une exception IOException, il est fort probable que vous connaissiez également un comportement par défaut/abstrait. Je pense que vous devriez définir une interface et déployer votre bibliothèque (avec une implémentation par défaut/abstraite) comme suit
public interface MyAmazingAPI {
Integer myMethod(String s) throws IOException;
}
Cependant, le problème du try-catch existe toujours pour le client. Si j'utilise votre API dans le flux, j'ai toujours besoin de gérer l'IOException dans un bloc try-catch hideux.
Fournissez une API par défaut conviviale pour les flux, comme suit
public interface MyAmazingAPI {
Integer myMethod(String s) throws IOException;
default Optional<Integer> myMethod(String s, Consumer<? super Exception> exceptionConsumer) {
try {
return Optional.ofNullable(this.myMethod(s));
} catch (Exception e) {
if (exceptionConsumer != null) {
exceptionConsumer.accept(e);
} else {
e.printStackTrace();
}
}
return Optional.empty();
}
}
La méthode par défaut prend l'objet consommateur en argument, qui sera responsable de gérer l'exception. Du point de vue du client, le code ressemblera à ceci:
strStream.map(str -> amazingAPIs.myMethod(str, Exception::printStackTrace))
.filter(Optional::isPresent)
.map(Optional::get).collect(toList());
Bonne droite? Bien sûr, un enregistreur ou une autre logique de traitement pourrait être utilisé à la place de Exception :: printStackTrace.
Vous pouvez également exposer une méthode similaire à https://docs.Oracle.com/javase/8/docs/api/Java/util/concurrent/CompletableFuture.html#exceptionally-Java.util.function.Function- . Ce qui signifie que vous pouvez exposer une autre méthode, qui contiendra l'exception de l'appel de la méthode précédente. L'inconvénient est que vous rendez maintenant vos API dynamiques, ce qui signifie que vous devez gérer la sécurité des threads et que ces performances finiront par devenir un succès. Juste une option à considérer si.
Une autre solution utilisant un wrapper Function serait de renvoyer une instance d'un wrapper de votre résultat, par exemple Success, si tout se passe bien, soit une instance de, par exemple Failure.
Quelques codes pour clarifier les choses:
public interface ThrowableFunction<A, B> {
B apply(A a) throws Exception;
}
public abstract class Try<A> {
public static boolean isSuccess(Try tryy) {
return tryy instanceof Success;
}
public static <A, B> Function<A, Try<B>> tryOf(ThrowableFunction<A, B> function) {
return a -> {
try {
B result = function.apply(a);
return new Success<B>(result);
} catch (Exception e) {
return new Failure<>(e);
}
};
}
public abstract boolean isSuccess();
public boolean isError() {
return !isSuccess();
}
public abstract A getResult();
public abstract Exception getError();
}
public class Success<A> extends Try<A> {
private final A result;
public Success(A result) {
this.result = result;
}
@Override
public boolean isSuccess() {
return true;
}
@Override
public A getResult() {
return result;
}
@Override
public Exception getError() {
return new UnsupportedOperationException();
}
@Override
public boolean equals(Object that) {
if(!(that instanceof Success)) {
return false;
}
return Objects.equal(result, ((Success) that).getResult());
}
}
public class Failure<A> extends Try<A> {
private final Exception exception;
public Failure(Exception exception) {
this.exception = exception;
}
@Override
public boolean isSuccess() {
return false;
}
@Override
public A getResult() {
throw new UnsupportedOperationException();
}
@Override
public Exception getError() {
return exception;
}
}
Un cas d'utilisation simple:
List<Try<Integer>> result = Lists.newArrayList(1, 2, 3).stream().
map(Try.<Integer, Integer>tryOf(i -> someMethodThrowingAnException(i))).
collect(Collectors.toList());
Vous pouvez utiliser ET pour cela. ET est une petite bibliothèque Java 8 pour la conversion/traduction des exceptions.
Avec ET cela ressemble à ceci:
// Do this once
ExceptionTranslator et = ET.newConfiguration().done();
...
// if your method returns something
Function<String, Integer> f = (t) -> et.withReturningTranslation(() -> myMethod(t));
// if your method returns nothing
Consumer<String> c = (t) -> et.withTranslation(() -> myMethod(t));
Les instances ExceptionTranslator
sont thread-safe et peuvent être partagées par plusieurs composants. Vous pouvez configurer des règles de conversion d'exception plus spécifiques (par exemple, FooCheckedException -> BarRuntimeException
) si vous le souhaitez. Si aucune autre règle n'est disponible, les exceptions cochées sont automatiquement converties en RuntimeException
.
(Avertissement: je suis l'auteur d'ET)
Par défaut, Java 8 Function ne permet pas de lever une exception et, comme le suggèrent plusieurs réponses, il existe de nombreuses façons de l'obtenir.
@FunctionalInterface
public interface FunctionWithException<T, R, E extends Exception> {
R apply(T t) throws E;
}
Définir en tant que:
private FunctionWithException<String, Integer, IOException> myMethod = (str) -> {
if ("abc".equals(str)) {
throw new IOException();
}
return 1;
};
Et ajoutez throws
ou try/catch
la même exception dans la méthode de l'appelant.
Créez un type de retour personnalisé qui propagera l'exception vérifiée. C'est une alternative à la création d'une nouvelle interface qui reflète l'interface fonctionnelle existante avec la légère modification d'une "exception de projection" sur la méthode de l'interface fonctionnelle.
public static interface CheckedValueSupplier<V> {
public V get () throws Exception;
}
public class CheckedValue<V> {
private final V v;
private final Optional<Exception> opt;
public Value (V v) {
this.v = v;
}
public Value (Exception e) {
this.opt = Optional.of(e);
}
public V get () throws Exception {
if (opt.isPresent()) {
throw opt.get();
}
return v;
}
public Optional<Exception> getException () {
return opt;
}
public static <T> CheckedValue<T> returns (T t) {
return new CheckedValue<T>(t);
}
public static <T> CheckedValue<T> rethrows (Exception e) {
return new CheckedValue<T>(e);
}
public static <V> CheckedValue<V> from (CheckedValueSupplier<V> sup) {
try {
return CheckedValue.returns(sup.get());
} catch (Exception e) {
return Result.rethrows(e);
}
}
public static <V> CheckedValue<V> escalates (CheckedValueSupplier<V> sup) {
try {
return CheckedValue.returns(sup.get());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
// Don't use this pattern with FileReader, it's meant to be an
// example. FileReader is a Closeable resource and as such should
// be managed in a try-with-resources block or in another safe
// manner that will make sure it is closed properly.
// This will not compile as the FileReader constructor throws
// an IOException.
Function<String, FileReader> sToFr =
(fn) -> new FileReader(Paths.get(fn).toFile());
// Alternative, this will compile.
Function<String, CheckedValue<FileReader>> sToFr = (fn) -> {
return CheckedValue.from (
() -> new FileReader(Paths.get("/home/" + f).toFile()));
};
// Single record usage
// The call to get() will propagate the checked exception if it exists.
FileReader readMe = pToFr.apply("/home/README").get();
// List of records usage
List<String> paths = ...; //a list of paths to files
Collection<CheckedValue<FileReader>> frs =
paths.stream().map(pToFr).collect(Collectors.toList());
// Find out if creation of a file reader failed.
boolean anyErrors = frs.stream()
.filter(f -> f.getException().isPresent())
.findAny().isPresent();
Ajouter "exception d'exception" à chaque interface fonctionnelle du kit JDK violerait le principe DRY de la manière la plus odieuse. Afin d'éviter cela, une interface fonctionnelle unique générant une exception vérifiée est créée (CheckedValueSupplier
). Ce sera la seule interface fonctionnelle qui autorise les exceptions vérifiées. Toutes les autres interfaces fonctionnelles utiliseront la CheckedValueSupplier
pour envelopper tout code qui lève une exception vérifiée.
La classe CheckedValue
conservera le résultat de l'exécution de toute logique qui lève une exception vérifiée. Cela empêche la propagation d'une exception vérifiée jusqu'au moment où le code tente d'accéder à la valeur contenue dans une instance de CheckedValue
.
CheckedValue#get()
soit appelé.Certaines interfaces fonctionnelles (Consumer
par exemple) doivent être gérées différemment car elles ne fournissent pas de valeur de retour.
Une approche consiste à utiliser une fonction au lieu d'un consommateur, qui s'applique lors de la gestion des flux.
List<String> lst = Lists.newArrayList();
// won't compile
lst.stream().forEach(e -> throwyMethod(e));
// compiles
lst.stream()
.map(e -> CheckedValueSupplier.from(
() -> {throwyMethod(e); return e;}))
.filter(v -> v.getException().isPresent()); //this example may not actually run due to lazy stream behavior
Sinon, vous pouvez toujours passer à RuntimeException
. Il existe d'autres réponses qui couvrent l'escalade d'une exception vérifiée à partir d'une Consumer
.
Il suffit d’éviter les interfaces fonctionnelles dans leur ensemble et d’utiliser une boucle de qualité supérieure.
Si cela ne vous dérange pas d'utiliser une bibliothèque tierce, avec cyclops-react , une bibliothèque à laquelle je contribue, vous pouvez utiliser l'API FluentFunctions pour écrire
Function<String, Integer> standardFn = FluentFunctions.ofChecked(this::myMethod);
ofChecked prend jOOλ CheckedFunction et renvoie la référence assouplie à une fonction JDK Java.util.function.Function standard (non cochée).
Sinon, vous pouvez continuer à utiliser la fonction capturée via l'API FluentFunctions!
Par exemple, pour exécuter votre méthode, réessayez-la 5 fois et enregistrez son statut, vous pouvez écrire
FluentFunctions.ofChecked(this::myMethod)
.log(s->log.debug(s),e->log.error(e,e.getMessage())
.try(5,1000)
.apply("my param");
Ce que je fais est de permettre à l'utilisateur de donner la valeur qu'il souhaite réellement en cas d'exception ..__
public static <T, R> Function<? super T, ? extends R> defaultIfThrows(FunctionThatThrows<? super T, ? extends R> delegate, R defaultValue) {
return x -> {
try {
return delegate.apply(x);
} catch (Throwable throwable) {
return defaultValue;
}
};
}
@FunctionalInterface
public interface FunctionThatThrows<T, R> {
R apply(T t) throws Throwable;
}
Et cela peut alors être appelé comme:
defaultIfThrows(child -> child.getID(), null)
Utilisez Jool Library
ou dites jOOλ library
à partir de JOOQ
. Il fournit non seulement des interfaces gérées par des exceptions non vérifiées mais fournit également à la classe Seq de nombreuses méthodes utiles.
En outre, il contient des interfaces fonctionnelles avec jusqu'à 16 paramètres. En outre, il fournit la classe Tuple qui est utilisée dans différents scénarios.
Spécifiquement dans la recherche de bibliothèque pour le package org.jooq.lambda.fi.util.function
. Il contient toutes les interfaces de Java-8 avec Checked ajouté. Voir ci-dessous pour référence: -
Je suis l'auteur d'une petite bibliothèque avec une magie générique pour lancer n'importe quelle exception Java n'importe où sans avoir besoin de les capturer ni de les envelopper dans RuntimeException
.
Utilisation: unchecked(() -> methodThrowingCheckedException())
public class UncheckedExceptions {
/**
* throws {@code exception} as unchecked exception, without wrapping exception.
*
* @return will never return anything, return type is set to {@code exception} only to be able to write <code>throw unchecked(exception)</code>
* @throws T {@code exception} as unchecked exception
*/
@SuppressWarnings("unchecked")
public static <T extends Throwable> T unchecked(Exception exception) throws T {
throw (T) exception;
}
@FunctionalInterface
public interface UncheckedFunction<R> {
R call() throws Exception;
}
/**
* Executes given function,
* catches and rethrows checked exceptions as unchecked exceptions, without wrapping exception.
*
* @return result of function
* @see #unchecked(Exception)
*/
public static <R> R unchecked(UncheckedFunction<R> function) {
try {
return function.call();
} catch (Exception e) {
throw unchecked(e);
}
}
@FunctionalInterface
public interface UncheckedMethod {
void call() throws Exception;
}
/**
* Executes given method,
* catches and rethrows checked exceptions as unchecked exceptions, without wrapping exception.
*
* @see #unchecked(Exception)
*/
public static void unchecked(UncheckedMethod method) {
try {
method.call();
} catch (Exception e) {
throw unchecked(e);
}
}
}
Je vais faire quelque chose de générique:
public interface Lambda {
@FunctionalInterface
public interface CheckedFunction<T> {
T get() throws Exception;
}
public static <T> T handle(CheckedFunction<T> supplier) {
try {
return supplier.get();
} catch (Exception exception) {
throw new RuntimeException(exception);
}
}
}
usage:
Lambda.handle(() -> method());
Plusieurs des solutions proposées utilisent un argument générique de E pour transmettre le type de l'exception qui est levée.
Allez plus loin, et plutôt que de passer du type d'exception à un consommateur du type d'exception, comme dans ...
Consumer<E extends Exception>
Vous pouvez créer plusieurs variantes réutilisables de Consumer<Exception>
qui couvriraient les besoins courants de gestion des exceptions de votre application.