我知道如何创建一个有String参数并返回int的方法的引用,它是:
Function<String, Integer>
然而,如果函数抛出异常,比如它被定义为:
Integer myMethod(String s) throws IOException
我该如何定义这个引用呢?
我知道如何创建一个有String参数并返回int的方法的引用,它是:
Function<String, Integer>
然而,如果函数抛出异常,比如它被定义为:
Integer myMethod(String s) throws IOException
我该如何定义这个引用呢?
当前回答
我使用一个名为unchecked()的重载实用程序函数来处理多个用例。
一些用法示例
unchecked(() -> new File("hello.txt").createNewFile());
boolean fileWasCreated = unchecked(() -> new File("hello.txt").createNewFile());
myFiles.forEach(unchecked(file -> new File(file.path).createNewFile()));
支持工具
public class UncheckedUtils {
@FunctionalInterface
public interface ThrowingConsumer<T> {
void accept(T t) throws Exception;
}
@FunctionalInterface
public interface ThrowingSupplier<T> {
T get() throws Exception;
}
@FunctionalInterface
public interface ThrowingRunnable {
void run() throws Exception;
}
public static <T> Consumer<T> unchecked(
ThrowingConsumer<T> throwingConsumer
) {
return i -> {
try {
throwingConsumer.accept(i);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
};
}
public static <T> T unchecked(
ThrowingSupplier<T> throwingSupplier
) {
try {
return throwingSupplier.get();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public static void unchecked(
ThrowingRunnable throwing
) {
try {
throwing.run();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
其他回答
默认情况下,Java 8函数不允许抛出异常,正如在多个回答中所建议的那样,有许多方法来实现它,其中一种方法是:
@FunctionalInterface
public interface FunctionWithException<T, R, E extends Exception> {
R apply(T t) throws E;
}
定义为:
private FunctionWithException<String, Integer, IOException> myMethod = (str) -> {
if ("abc".equals(str)) {
throw new IOException();
}
return 1;
};
并在调用者方法中添加抛出或尝试/捕获相同的异常。
这个问题也一直困扰着我;这就是我创建这个项目的原因。
用它你可以做:
final ThrowingFunction<String, Integer> f = yourMethodReferenceHere;
JDK总共定义了39个接口,它们都有类似的抛出功能;这些都是流中使用的@ functionalinterface(基本流,还有IntStream, LongStream和DoubleStream)。
当它们中的每一个都扩展了它们的非抛出对应对象时,你也可以直接在lambdas中使用它们:
myStringStream.map(f) // <-- works
默认行为是,当您抛出lambda抛出一个检查异常时,抛出一个ThrownByLambdaException,并将检查异常作为原因。因此,您可以捕捉到它并得到原因。
其他特性也可用。
您需要执行以下操作之一。
If it's your code, then define your own functional interface that declares the checked exception: @FunctionalInterface public interface CheckedFunction<T, R> { R apply(T t) throws IOException; } and use it: void foo (CheckedFunction f) { ... } Otherwise, wrap Integer myMethod(String s) in a method that doesn't declare a checked exception: public Integer myWrappedMethod(String s) { try { return myMethod(s); } catch(IOException e) { throw new UncheckedIOException(e); } } and then: Function<String, Integer> f = (String t) -> myWrappedMethod(t); or: Function<String, Integer> f = (String t) -> { try { return myMethod(t); } catch(IOException e) { throw new UncheckedIOException(e); } };
我认为榴莲的错误课程结合了上面各种建议的许多优点。
将抛出函数包装到标准Java 8函数接口。 轻松指定各种处理错误的策略 在包装返回值的方法时,指定默认值和重新抛出RuntimeException之间有重要区别。 抛出Java 8的函数接口版本 类似于fge的答案 用于抛出特定异常的标准接口 这解决了Zoltán的问题
在你的项目中加入榴莲,你可以:
从jcenter或maven中心com.diffplug.durian:durian:3.3.0获取 或者只是复制粘贴两个小类到你的代码中:throws .java和Errors.java
一些提供的解决方案使用E的泛型参数来传递抛出的异常类型。
更进一步,不是传递异常的类型,而是传递异常类型的Consumer,如……
Consumer<E extends Exception>
您可以创建几个Consumer<Exception>的可重用变体,这些变体将覆盖应用程序的常见异常处理需求。