La fonction Lambda de Java 8 qui fait exception?

je sais comment créer une référence à une méthode qui a un paramètre String et renvoie un int , c'est:

Function<String, Integer>

cependant, cela ne fonctionne pas si la fonction lance une exception, dire qu'il est défini comme:

Integer myMethod(String s) throws IOException

comment définirais-Je cette référence?

351
demandé sur Lonely Neuron 2013-08-13 03:16:36

23 réponses

vous aurez besoin de faire l'un des suivants.

  • si c'est votre code, alors définissez votre propre interface fonctionnelle qui déclare l'exception cochée

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

    et l'utiliser

    void foo (CheckedFunction f) { ... }
    
  • sinon, envelopper Integer myMethod(String s) dans une méthode qui ne déclare pas une exception cochée:

    public Integer myWrappedMethod(String s) {
        try {
            return myMethod(s);
        }
        catch(IOException e) {
            throw new UncheckedIOException(e);
        }
    }
    

    puis

    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);
            }
        };
    
312
répondu jason 2015-10-28 09:44:05

vous pouvez en fait prolonger Consumer (et Function etc.) avec une nouvelle interface qui gère les exceptions -- en utilisant les méthodes par défaut de Java 8 !

Considérer cette interface (s'é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 ex. avec forEach ) avec un code qui lance des exceptions, vous ont traditionnellement mis en place un bloc d'essai/prise:

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 tout simplement mouler pour être plus succinct!:

list.forEach((ThrowingConsumer<String>) aps -> {
    // maybe some other code here...
    throw new Exception("asda");
});

mise à jour : on dirait qu'il y a une très belle bibliothèque utilitaire partie de Durian appelé erreurs qui peut être utilisé pour résoudre ce problème avec beaucoup plus de flexibilité. Par exemple, dans mon implémentation ci-dessus, j'ai explicitement défini la Politique de gestion des erreurs ( System.out... ou throw RuntimeException ), alors que les erreurs de Durian vous permettent d'appliquer une politique à la volée via une large série de méthodes utilitaires. Merci pour partager , @NedTwigg!.

exemple d'utilisation:

list.forEach(Errors.rethrow().wrap(c -> somethingThatThrows(c)));
158
répondu jlb 2017-07-30 10:25:01

je pense Durian Errors classe combine plusieurs des avantages des diverses suggestions ci-dessus.

pour inclure Durian dans votre projet, vous pouvez soit:

52
répondu Ned Twigg 2017-05-23 12:10:48

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
}
23
répondu assylias 2013-08-12 23:36:50

avertissement: Je n'ai pas encore utilisé Java 8, seulement lu à ce sujet.

Function<String, Integer> ne lance pas IOException , donc vous ne pouvez pas mettre de code que throws IOException . Si vous appelez une méthode qui attend un Function<String, Integer> , alors la lambda que vous passez à cette méthode ne peut pas jeter IOException , période. 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 passez la lambda est celle que vous avez écrite vous-même, vous pouvez définir une nouvelle interface fonctionnelle et l'utiliser comme le type de paramètre au lieu de Function<String, Integer> :

public interface FunctionThatThrowsIOException<I, O> {
    O apply(I input) throws IOException;
}
11
répondu Adam R. Nelson 2013-08-12 23:30:57

si vous n'avez pas l'esprit d'utiliser un tiers lib ( Vavr ) vous pouvez écrire

CheckedFunction1<String, Integer> f = this::myMethod;

il a également le soi-disant Try monad qui traite 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 la suite ici .

clause de non-responsabilité: je suis le créateur de Vavr.

7
répondu Daniel Dietrich 2017-04-29 19:38:45

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);
6
répondu SeregaLBN 2016-03-08 22:13:23

vous pouvez.

extension du UtilException de @marcg et ajout du <E extends Exception> générique lorsque nécessaire: de cette façon, le compilateur vous forcera à nouveau à ajouter des clauses de rejet et tout se passe comme si vous pouviez lancer des exceptions vérifiées nativement sur les flux de 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 { }
}
5
répondu PaoloC 2015-07-03 10:35:10

j'ai eu ce problème avec la Classe.forName et de la Classe.nouvelle substance à l'intérieur d'un lambda, donc je viens de faire:

public Object uncheckedNewInstanceForName (String name) {

    try {
        return Class.forName(name).newInstance();
    }
    catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

dans la lambda, au lieu d'appeler la classe.forName("maclasse").newInstance () je viens d'appeler uncheckedNewInstanceForName ("myClass")

4
répondu Sergio 2015-01-17 12:21:18

vous pouvez cependant créer votre propre Interfacefonctionnel qui lance comme ci-dessous..

@FunctionalInterface
public interface UseInstance<T, X extends Throwable> {
  void accept(T instance) throws X;
}

puis l'implémenter en utilisant Lambdas ou 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");

 }

}
4
répondu JohnnyO 2015-05-30 22:48:52

une autre solution utilisant une fonction wrapper serait de retourner soit une instance d'un wrapper de votre résultat, dire succès, si tout allait bien, soit une instance de, disons échec.

un code 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());
3
répondu yohan 2014-01-30 13:37:19

ce problème me dérange aussi; c'est pourquoi j'ai créé ce projet .

avec elle vous pouvez faire:

final ThrowingFunction<String, Integer> f = yourMethodReferenceHere;

il y a un total de 39 interfaces définies par le JDK qui ont un tel équivalent Throwing ; ce sont toutes les @FunctionalInterface utilisées dans les flux (la base Stream mais aussi IntStream , LongStream et DoubleStream ).

et comme chacun d'eux s'étendent leur contrepartie non lanceur, vous pouvez les utiliser directement dans lambdas ainsi:

myStringStream.map(f) // <-- works

le comportement par défaut est que lorsque votre LAMBDA jeter une exception vérifiée, un ThrownByLambdaException est lancé avec l'exception vérifiée comme cause. Vous pouvez donc capturer cela et obtenir la cause.

d'Autres fonctionnalités sont également disponibles.

3
répondu fge 2014-12-29 22:00:59

vous pouvez utiliser ET pour cela. ET est une petite bibliothèque Java 8 pour la conversion/traduction d'exception.

avec ET il 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 sécurisées 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 .

(Disclaimer: je suis l'auteur de HE)

3
répondu micha 2015-09-03 07:21:33

Sournois jeter idiome permet de contourner les CheckedException de l'expression Lambda. Envelopper un CheckedException dans un RuntimeException n'est pas bon pour la manipulation stricte des erreurs.

il peut être utilisé comme une fonction Consumer utilisée dans une collection Java.

Voici une version simple et améliorée de 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);
        }
    }));
}

ce vient d'envelopper le lambda dans un renvoyer . Il fait CheckedException rethrow n'importe quel Exception qui a été jeté 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;
    }

}

trouver un code complet et des tests unitaires ici .

3
répondu myui 2018-07-01 14:29:01

il y a beaucoup de bonnes réponses déjà publiées ici. J'essaie juste de résoudre le problème avec une perspective différente. C'est juste mes 2 cents, s'il vous plaît corrigez-moi si je me trompe quelque part.

la clause des lancements dans L'Interfacefonctionnel n'est pas une bonne idée

je pense que ce n'est probablement pas une bonne idée d'appliquer throws IOException à cause des raisons suivantes

  • Ce on dirait un anti-motif pour Stream / Lambda. L'idée est que l'appelant décider de ce code et comment traiter l'exception. Dans de nombreux cas, L'Exception IOException pourrait ne pas s'appliquer au client. Par exemple, si le client obtient de la valeur à partir de cache / mémoire au lieu d'effectuer l'entrée/sortie réelle

  • aussi, les exceptions manipulation dans les cours d'eau devient vraiment hideux. Par exemple, voici mon code est comme 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;
                });
    

    laid n'est-ce pas? En outre, comme je l'ai mentionné dans mon premier point, que la méthode d'opér ation de dos peut ou non lancer IOException (en fonction de l'implémentation du client/appelant), mais en raison de la clause de lancer dans votre méthode D'Interfacefonctionnel, je dois toujours écrire le try-catch.

Que dois-je faire si je sais vraiment cette API throws IOException

  • alors, nous confondons probablement Fonctionnellementl'Interfaceavec des Interfaces typiques. Si vous savez que cette API va lancer IOException, alors vous connaissez probablement aussi un comportement par défaut/abstrait. Je pense que vous devriez définir une interface et déployer votre bibliothèque (avec implémentation par défaut/abstract) comme suit

    public interface MyAmazingAPI {
        Integer myMethod(String s) throws IOException;
    }
    

    mais, le problème de try-catch existe toujours pour le client. Si j'utilise votre API dans stream, je dois quand même gérer IOException dans hideux bloc try-catch.

  • Fournir une valeur par défaut stream-friendly API 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 comme argument, qui sera responsable de gérer l'exception. Maintenant, 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());
    

    Bel à droite? Bien sûr, logger ou autre logique de manipulation pourrait être utilisé au lieu 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 du précédent appel de méthode. L'inconvénient est que vous faites maintenant votre APIs staeful, ce qui signifie que vous devez gérer thread-safety et qui finira par devenir un succès de performance. Juste une option à envisager.

2
répondu TriCore 2016-01-03 08:10:29

créer un type de retour personnalisé qui propagera l'exception cochée. C'est une alternative à la création d'une nouvelle interface qui reflète l'existant interface fonctionnelle avec la légère modification d'une "throws exception" sur l'interface fonctionnelle de la méthode.

définition

CheckedValueSupplier

public static interface CheckedValueSupplier<V> {
    public V get () throws Exception;
}

CheckedValue

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

}

Utilisation

//  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();

que se passe-t-il?

ajouter "jette exception" à chaque interface fonctionnelle dans le JDK violerait le principe sec d'une manière des plus odieuses. Pour éviter cela, une seule interface fonctionnelle qui lance une exception cochée est créée ( CheckedValueSupplier ). Ce sera la seule interface fonctionnelle qui autorise les exceptions vérifiées. Toutes les autres interfaces fonctionnelles vont utiliser le CheckedValueSupplier pour envelopper n'importe quel code qui jette un coché exception.

la classe CheckedValue tiendra le résultat de l'exécution de toute logique qui jette une exception cochée. Cela empêche la propagation d'une exception cochée jusqu'au point où le code tente d'accéder à la valeur qu'une instance de CheckedValue contient.

Les problèmes avec cette approche.

  • nous lançons maintenant" Exception " masquant effectivement le type spécifique lancé à l'origine.
  • nous ignorons qu'une exception s'est produite jusqu'à ce que CheckedValue#get() soit appelé.
"1519140920 du Consommateur" et al

certaines interfaces fonctionnelles ( Consumer par exemple) doivent être manipulées d'une manière différente car elles ne fournissent pas de valeur de retour.

fonction tenant lieu de consommateur

une approche consiste à utiliser une fonction au lieu d'un consommateur, ce qui s'applique lors de la manipulation 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

Dégénérer

alternativement, vous pouvez toujours monter à un RuntimeException . Il y a d'autres réponses qui couvrent l'indexation d'une exception cochée à l'intérieur d'un Consumer .

ne consommez pas.

il suffit d'éviter les interfaces fonctionnelles tous ensemble et d'utiliser un bon-ole-fashioned pour boucle.

2
répondu justin.hughey 2016-08-30 15:06:28

par défaut, Java 8 fonction ne permet pas de jeter l'exception et comme suggéré dans les réponses multiples Il ya plusieurs façons de le réaliser, une façon est:

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

Définir comme:

private FunctionWithException<String, Integer, IOException> myMethod = (str) -> {
    if ("abc".equals(str)) {
        throw new IOException();
    }
  return 1;
};

et ajouter throws ou try/catch la même exception dans la méthode de l'appelant.

2
répondu Arpit 2017-02-13 15:44:18

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 le FluentFunctions API to write

 Function<String, Integer> standardFn = FluentFunctions.ofChecked(this::myMethod);

ofChecked prend une fonction de vérification de jOOλ et renvoie la référence adoucie à un java standard (non vérifié) de JDK.util.fonction.Fonction.

vous pouvez aussi continuer à travailler avec la fonction capturée via les fonctions fluentes api!

par exemple pour exécuter votre méthode, en la retraçant jusqu'à 5 fois et en enregistrant 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");
1
répondu John McClean 2016-02-24 15:56:57

Ce que je fais est de permettre à l'utilisateur de donner la valeur qu'il fait envie en cas d'exception . Donc j'ai quelque chose qui ressemble à ça

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)
0
répondu mmounirou 2014-09-30 12:37:50

plusieurs des solutions proposées utilisent un argument générique de E pour passer dans le type de l'exception qui est lancée.

encore plus loin, et plutôt que de passer dans le type de l'exception, passer d'un Consommateur de type d'exception, comme dans...

Consumer<E extends Exception>

vous pourriez créer plusieurs variantes réutilisables de Consumer<Exception> qui couvriraient les besoins communs de traitement des exceptions de votre application.

0
répondu Rodney P. Barbati 2017-06-12 16:07:34

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

        }
    }
}

utilisation:

 Lambda.handle(() -> method());
0
répondu ahll 2017-07-21 11:23:06

utilisez Jool Library ou dites jOOλ library de JOOQ . Non seulement il fournit des interfaces d'exception gérées non vérifiées, mais il fournit également Seq class avec beaucoup de méthodes utiles.

contient aussi des Interfaces fonctionnelles avec jusqu'à 16 paramètres. De plus, il fournit la classe Tuple qui est utilisée dans différents scénarios.

Jool Git Link

spécifiquement dans la recherche de bibliothèque pour org.jooq.lambda.fi.util.function paquet. Il contient toutes les Interfaces de Java 8 avec Vérifiée ajouté. Voir ci-dessous pour référence:-

enter image description here

0
répondu Vinay Prajapati 2017-12-12 09:22:59
public void frankTest() {
    int pageId= -1;

    List<Book> users= null;
    try {
        //Does Not Compile:  Object page=DatabaseConnection.getSpringConnection().queryForObject("SELECT * FROM bookmark_page", (rw, n) -> new Portal(rw.getInt("id"), "", users.parallelStream().filter(uu -> uu.getVbid() == rw.getString("user_id")).findFirst().get(), rw.getString("name")));

        //Compiles:
        Object page= DatabaseConnection.getSpringConnection().queryForObject("SELECT * FROM bookmark_page", (rw, n) -> { 
            try {
                final Book bk= users.stream().filter(bp -> { 
                    String name= null;
                    try {
                        name = rw.getString("name");
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    return bp.getTitle().equals(name); 
                }).limit(1).collect(Collectors.toList()).get(0);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return new Portal(rw.getInt("id"), "", users.get(0), rw.getString("name")); 
        } );
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
-7
répondu Franky Knuckels 2015-01-25 19:37:54