it-swarm.com.de

Java 8 Lambda-Funktion, die eine Ausnahme auslöst?

Ich kann einen Verweis auf eine Methode erstellen, die einen String-Parameter enthält und eine int zurückgibt.

Function<String, Integer>

Dies funktioniert jedoch nicht, wenn die Funktion eine Ausnahme auslöst, zum Beispiel:

Integer myMethod(String s) throws IOException

Wie würde ich diese Referenz definieren?

384
Triton Man

Sie müssen einen der folgenden Schritte ausführen.

  • Wenn es sich um Ihren Code handelt, definieren Sie Ihre eigene Funktionsschnittstelle, die die geprüfte Ausnahme deklariert

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

    und benutze es

    void foo (CheckedFunction f) { ... }
    
  • Andernfalls wickeln Sie Integer myMethod(String s) in eine Methode ein, die keine geprüfte Ausnahme deklariert:

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

    und dann

    Function<String, Integer> f = (String t) -> myWrappedMethod(t);
    

    oder

    Function<String, Integer> f =
        (String t) -> {
            try {
               return myMethod(t);
            }
            catch(IOException e) {
                throw new UncheckedIOException(e);
            }
        };
    
338
jason

Sie können Consumer (und Function usw.) tatsächlich um eine neue Schnittstelle erweitern, die Ausnahmen behandelt - mit den default-Methoden von Java 8!

Betrachten Sie diese Schnittstelle (erweitert 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;

}

Dann zum Beispiel, wenn Sie eine Liste haben:

final List<String> list = Arrays.asList("A", "B", "C");

Wenn Sie es mit etwas Code, der Ausnahmen auslöst (z. B. mit forEach) verbrauchen möchten, hätten Sie normalerweise einen try/catch-Block eingerichtet:

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

Mit dieser neuen Schnittstelle können Sie sie jedoch mit einem Lambda-Ausdruck instanziieren, und der Compiler beschwert sich nicht:

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

Oder werfen Sie es einfach nur knapper aus !:

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

Update: Anscheinend gibt es eine sehr schöne Utility-Bibliothek in Durian called Errors , die verwendet werden kann, um dieses Problem mit viel mehr Flexibilität zu lösen. In meiner obigen Implementierung habe ich zum Beispiel die Fehlerbehandlungsrichtlinie (System.out... oder throw RuntimeException) explizit definiert, wohingegen Durian's Errors es Ihnen ermöglichen, eine Richtlinie über eine große Reihe von Dienstprogrammmethoden im laufenden Betrieb anzuwenden. Vielen Dank, dass Sie es teilen , @NedTwigg !.

Verwendungsbeispiel:

list.forEach(Errors.rethrow().wrap(c -> somethingThatThrows(c)));
170
jlb

Ich denke, Durians Errors class kombiniert viele der Profis der verschiedenen oben genannten Vorschläge.

Um Durian in Ihr Projekt aufzunehmen, haben Sie folgende Möglichkeiten:

55
Ned Twigg

Dies ist nicht spezifisch für Java 8. Sie versuchen, etwas Äquivalentes zu kompilieren:

interface I {
    void m();
}
class C implements I {
    public void m() throws Exception {} //can't compile
}
25
assylias

Disclaimer: Ich habe Java 8 noch nicht verwendet, nur darüber gelesen.

Function<String, Integer> löst keine IOException aus. Sie können also keinen Code eingeben, der throws IOException ist. Wenn Sie eine Methode aufrufen, die einen Function<String, Integer> erwartet, kann das Lambda, das Sie an diese Methode übergeben, keine IOException, Punkt auslösen. Sie können entweder ein Lambda wie folgt schreiben (ich denke, das ist die Lambda-Syntax, nicht sicher):

(String s) -> {
    try {
        return myMethod(s);
    } catch (IOException ex) {
        throw new RuntimeException(ex);
        // (Or do something else with it...)
    }
}

Wenn die Methode, an die Sie das Lambda übergeben, eine Methode ist, die Sie selbst geschrieben haben, können Sie eine neue funktionale Schnittstelle definieren und diese als Parametertyp anstelle von Function<String, Integer> verwenden:

public interface FunctionThatThrowsIOException<I, O> {
    O apply(I input) throws IOException;
}
11
Adam R. Nelson

Wenn es Ihnen nichts ausmacht, eine 3rd Party-Bibliothek ( Vavr ) zu verwenden, können Sie schreiben

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

Es hat auch die sogenannte Try-Monade, die Fehler behandelt:

Try(() -> f.apply("test")) // results in a Success(Integer) or Failure(Throwable)
        .map(i -> ...) // only executed on Success
        ...

Bitte lesen Sie mehr hier .

Haftungsausschluss: Ich bin der Schöpfer von Vavr.

7
Daniel Dietrich

Sie können den Wrapper verwenden

Function<String, Integer> func1 = s -> Unthrow.wrap(() -> myMethod(s));

oder

Function<String, Integer> func2 = s1 -> Unthrow.wrap((s2) -> myMethod(s2), s1);
6
SeregaLBN

Sie können.

Erweitern von @marcgs UtilException und Hinzufügen von generischem <E extends Exception> bei Bedarf: Auf diese Weise zwingt der Compiler Sie erneut, Wurfklauseln und alles hinzuzufügen, als könnten Sie aktivierte Ausnahmen in Java 8-Streams werfen.

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
PaoloC

Dieses Problem hat mich auch gestört; Deshalb habe ich dieses Projekt erstellt.

Damit können Sie:

final ThrowingFunction<String, Integer> f = yourMethodReferenceHere;

Es gibt insgesamt 39 Schnittstellen, die durch das JDK definiert sind und über ein solches Throwing-Äquivalent verfügen. Dies sind alles @FunctionalInterfaces, die in Streams verwendet werden (die Basis Stream, aber auch IntStream, LongStream und DoubleStream).

Und da jeder sein nicht-werfendes Pendant erweitert, können Sie sie auch direkt in Lambdas verwenden:

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

Das Standardverhalten ist, dass, wenn Ihr werfendes Lambda eine geprüfte Ausnahme auslöst, eine ThrownByLambdaException mit der geprüften Ausnahme als Ursache ausgelöst wird. Sie können das also erfassen und die Ursache ermitteln.

Andere Funktionen sind ebenfalls verfügbar.

4
fge

Sie können jedoch Ihr eigenes FunctionalInterface erstellen, das wie folgt wirft.

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

dann implementieren Sie es mit Lambdas oder Referenzen wie unten gezeigt.

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
JohnnyO

Sneaky Throw Idiom ermöglicht das Umgehen von CheckedException des Lambda-Ausdrucks. Das Einbetten einer CheckedException in eine RuntimeException ist nicht geeignet für die strikte Fehlerbehandlung.

Sie kann als Consumer - Funktion verwendet werden, die in einer Java-Sammlung verwendet wird.

Hier ist eine einfache und verbesserte Version von Antwort von 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);
        }
    }));
}

Dies umschließt das Lambda nur in einem rethrow. Dies bewirkt, dass CheckedException alle Exception-Werte erneut in den Lambda-Speicher werfen kann.

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

}

Finden Sie einen vollständigen Code und Komponententests hier .

4
myui

Ich hatte dieses Problem mit Class.forName und Class.newInstance in einem Lambda, also tat ich gerade:

public Object uncheckedNewInstanceForName (String name) {

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

Innerhalb des Lambda, anstatt Class.forName ("myClass"). NewInstance () aufzurufen, habe ich uncheckedNewInstanceForName ("myClass")

4
Sergio

Hier gibt es bereits viele großartige Antworten. Versuchen Sie einfach, das Problem aus einer anderen Perspektive zu lösen. Es sind nur meine 2 Cent, bitte korrigieren Sie mich, wenn ich mich irgendwo irre. 

Throws-Klausel in FunctionalInterface ist keine gute Idee

Ich denke, das ist wahrscheinlich keine gute Idee, um IOException aus folgenden Gründen zu erzwingen

  • Das sieht für mich nach einem Anti-Pattern gegen Stream/Lambda aus. Die ganze Idee ist, dass der Aufrufer entscheidet, welcher Code bereitgestellt wird und wie die Ausnahme behandelt werden soll. In vielen Szenarien ist die IOException möglicherweise nicht für den Client anwendbar. Zum Beispiel, wenn der Client einen Wert aus dem Cache/Speicher erhält, anstatt die eigentliche E/A durchzuführen. 

  • Auch die Ausnahmenbehandlung in Streams wird wirklich abscheulich. Zum Beispiel sieht mein Code so aus, wenn ich Ihre API verwende

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

    Hässlich ist es nicht? Wie ich bereits an erster Stelle erwähnt habe, kann die doSomeOperation-Methode (je nach Implementierung des Clients/Aufrufers) IOException auslösen oder nicht, aber aufgrund der throws-Klausel in Ihrer FunctionalInterface-Methode muss ich immer die Try-Catch.

Was mache ich, wenn ich wirklich weiß, dass diese API IOException auslöst?

  • Dann verwechseln wir wahrscheinlich FunctionalInterface mit typischen Interfaces. Wenn Sie wissen, dass diese API IOException auslöst, kennen Sie wahrscheinlich auch ein Standard-/abstraktes Verhalten. Ich denke, Sie sollten eine Schnittstelle definieren und Ihre Bibliothek (mit standardmäßiger/abstrakter Implementierung) wie folgt bereitstellen

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

    Das Try-Catch-Problem besteht jedoch weiterhin für den Client. Wenn ich Ihre API im Stream verwende, muss ich IOException noch in einem hässlichen try-catch-Block behandeln.

  • Stellen Sie eine standard-Stream-freundliche API wie folgt bereit

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

    Die Standardmethode verwendet das Consumer-Objekt als Argument, das für die Behandlung der Ausnahme zuständig ist. Aus der Sicht des Kunden sieht der Code nun so aus

    strStream.map(str -> amazingAPIs.myMethod(str, Exception::printStackTrace))
                    .filter(Optional::isPresent)
                    .map(Optional::get).collect(toList());
    

    Schön, richtig? Natürlich kann anstelle von Exception :: printStackTrace auch ein Logger oder eine andere Verarbeitungslogik verwendet werden. 

  • Sie können auch eine Methode verfügbar machen, die https://docs.Oracle.com/javase/8/docs/api/Java/util/concurrent/CompletableFuture.html#exceptionally-Java.util.function.Function- ähnelt. . Das bedeutet, dass Sie eine andere Methode verfügbar machen können, die die Ausnahme vom vorherigen Methodenaufruf enthält. Der Nachteil ist, dass Sie jetzt Ihre APIs zustandsbehaftet machen, was bedeutet, dass Sie mit Thread-Sicherheit umgehen müssen, was schließlich zu einem Performance-Hit wird. Nur eine Option zu prüfen. 

3
TriCore

Eine andere Lösung, die einen Function-Wrapper verwendet, besteht darin, entweder eine Instanz eines Wrappers Ihres Ergebnisses zurückzugeben, z. B. Erfolg, wenn alles gut lief, entweder eine Instanz von, z.

Ein Code, um Dinge zu klären:

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

Ein einfacher Anwendungsfall:

List<Try<Integer>> result = Lists.newArrayList(1, 2, 3).stream().
    map(Try.<Integer, Integer>tryOf(i -> someMethodThrowingAnException(i))).
    collect(Collectors.toList());
3
yohan

Sie können dazu ET verwenden. ET ist eine kleine Java 8-Bibliothek für die Konvertierung/Übersetzung von Ausnahmen.

Bei ET sieht es so aus:

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

ExceptionTranslator-Instanzen sind threadsicher und können von mehreren Komponenten gemeinsam genutzt werden. Sie können auch spezifischere Ausnahmekonvertierungsregeln (z. B. FooCheckedException -> BarRuntimeException) konfigurieren, wenn Sie möchten. Wenn keine anderen Regeln verfügbar sind, werden markierte Ausnahmen automatisch in RuntimeException konvertiert.

(Haftungsausschluss: Ich bin der Autor von ET)

3
micha

Standardmäßig erlaubt Java 8 Function keine Ausnahme, und wie in mehreren Antworten vorgeschlagen, gibt es viele Möglichkeiten, dies zu erreichen. Eine Möglichkeit ist:

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

Definiere als:

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

Fügen Sie throws oder try/catch dieselbe Ausnahme in der Aufrufermethode hinzu.

2
Arpit

Erstellen Sie einen benutzerdefinierten Rückgabetyp, der die geprüfte Ausnahme weitergibt. Dies ist eine Alternative zum Erstellen einer neuen Schnittstelle, die die vorhandene funktionale Schnittstelle widerspiegelt, mit der geringfügigen Änderung einer "wirft eine Ausnahme" für die Methode der funktionalen Schnittstelle.

Definition

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

}

Verwendungszweck

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

Was ist los?

Das Hinzufügen von "Ausnahmen" zu jeder funktionalen Schnittstelle im JDK würde das DRY - Prinzip auf abscheulichste Weise verletzen. Um dies zu vermeiden, wird eine einzige funktionale Schnittstelle erstellt, die eine geprüfte Ausnahme auslöst (CheckedValueSupplier). Dies ist die einzige funktionale Schnittstelle, die geprüfte Ausnahmen zulässt. Alle anderen funktionalen Schnittstellen nutzen die Variable CheckedValueSupplier, um Code zu umbrechen, der eine geprüfte Ausnahme auslöst.

Die CheckedValue-Klasse enthält das Ergebnis der Ausführung einer Logik, die eine geprüfte Ausnahme auslöst. Dadurch wird die Weitergabe einer geprüften Ausnahme bis zu dem Punkt verhindert, an dem Code versucht, auf den Wert zuzugreifen, den eine Instanz von CheckedValue enthält.

Die Probleme mit diesem Ansatz.

  • Wir werfen jetzt "Exception", um den ursprünglich geworfenen Typ effektiv zu verbergen.
  • Wir wissen nicht, dass eine Ausnahme aufgetreten ist, bis CheckedValue#get() aufgerufen wird.

Consumer et al

Einige funktionale Schnittstellen (zum Beispiel Consumer) müssen anders gehandhabt werden, da sie keinen Rückgabewert liefern.

Funktion anstelle des Verbrauchers

Ein Ansatz besteht darin, eine Funktion anstelle eines Konsumenten zu verwenden, was beim Umgang mit Streams gilt.

    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

Eskalieren

Alternativ können Sie immer zu einer RuntimeException eskalieren. Es gibt andere Antworten, die die Eskalation einer geprüften Ausnahme aus einer Consumer abdecken.

Nicht konsumieren.

Vermeiden Sie einfach alle funktionalen Schnittstellen und verwenden Sie eine gut gebaute for-Schleife.

2
justin.hughey

Wenn es Ihnen nichts ausmacht, eine Drittanbieter-Bibliothek zu verwenden, mit cyclops-react , einer Bibliothek, zu der ich beitrage, können Sie die FluentFunctions API zum Schreiben verwenden

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

ofChecked verwendet eine jOOλ CheckedFunction und gibt die weich gemachte Referenz auf eine standardmäßige (ungeprüfte) JDK Java.util.function.Function zurück.

Alternativ können Sie mit der erfassten Funktion über die FluentFunctions-API weiterarbeiten.

Zum Beispiel, um Ihre Methode auszuführen, sie bis zu fünfmal auszuführen und den Status zu protokollieren, den Sie schreiben können 

  FluentFunctions.ofChecked(this::myMethod)
                 .log(s->log.debug(s),e->log.error(e,e.getMessage())
                 .try(5,1000)
                 .apply("my param");
1
John McClean

Was ich mache ist, dem Benutzer zu gestatten, den Wert anzugeben, den er in Ausnahmefällen tatsächlich haben möchte 

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

Und das kann dann so aufgerufen werden: 

defaultIfThrows(child -> child.getID(), null)
1
mmounirou

Verwenden Sie Jool Library oder sagen Sie jOOλ library aus JOOQ. Es bietet nicht nur ungeprüfte Schnittstellen für die Behandlung von Ausnahmen, sondern auch die Seq-Klasse mit vielen nützlichen Methoden. 

Außerdem enthält es Funktionsschnittstellen mit bis zu 16 Parametern. Außerdem wird eine Tuple-Klasse bereitgestellt, die in verschiedenen Szenarien verwendet wird.

Jool Git Link

Speziell bei der Bibliotheksuche nach org.jooq.lambda.fi.util.function-Paket. Es enthält alle Schnittstellen von Java-8 mit angehängtem Checked. Siehe unten als Referenz: -

 enter image description here

0
Vinay Prajapati

Ich bin der Autor einer winzigen Bibliothek mit generischer Magie, mit der ich Java-Ausnahmen überall auslösen kann ohne sie abfangen oder in RuntimeException einwickeln zu müssen .

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

quelle: https://github.com/qoomon/unchecked-exceptions-Java

0
qoomon

Ich werde etwas generisches tun:

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

        }
    }
}

verwendungszweck:

 Lambda.handle(() -> method());
0
ahll

Einige der angebotenen Lösungen verwenden ein generisches Argument von E, um den Typ der Ausnahme zu übergeben, die ausgelöst wird.

Gehen Sie noch einen Schritt weiter und übergeben Sie nicht den Typ der Ausnahme, sondern einen Consumer der Art der Ausnahme, wie in ...

Consumer<E extends Exception>

Sie können mehrere wiederverwendbare Varianten von Consumer<Exception> erstellen, die die allgemeinen Ausnahmebehandlungsanforderungen Ihrer Anwendung abdecken. 

0