我知道如何创建一个有String参数并返回int的方法的引用,它是:
Function<String, Integer>
然而,如果函数抛出异常,比如它被定义为:
Integer myMethod(String s) throws IOException
我该如何定义这个引用呢?
我知道如何创建一个有String参数并返回int的方法的引用,它是:
Function<String, Integer>
然而,如果函数抛出异常,比如它被定义为:
Integer myMethod(String s) throws IOException
我该如何定义这个引用呢?
当前回答
如果你有lombok,你可以用@SneakyThrows注释你的方法
SneakyThrow不会静默地吞咽、包装到RuntimeException中,或以其他方式修改所列出的检查异常类型的任何异常。JVM不检查被检查异常系统的一致性;Javac可以,而且这个注释允许您选择不使用它的机制。
https://projectlombok.org/features/SneakyThrows
其他回答
我所做的是允许用户在异常情况下给出他实际想要的值。 我有一个像这样的东西
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;
}
这个可以被称为:
defaultIfThrows(child -> child.getID(), null)
免责声明:我还没有使用过Java 8,只是阅读过它。
Function<String, Integer>不抛出IOException,所以你不能在其中放入任何抛出IOException的代码。如果你正在调用一个期望Function<String, Integer>的方法,那么你传递给该方法的lambda不能抛出IOException,句号。你可以这样写一个lambda(我认为这是lambda语法,不确定):
(String s) -> {
try {
return myMethod(s);
} catch (IOException ex) {
throw new RuntimeException(ex);
// (Or do something else with it...)
}
}
或者,如果你传递lambda的方法是你自己写的,你可以定义一个新的函数接口,并使用它作为参数类型,而不是Function<String, Integer>:
public interface FunctionThatThrowsIOException<I, O> {
O apply(I input) throws IOException;
}
您需要执行以下操作之一。
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
Sneaky throw成语允许绕过Lambda表达式的CheckedException。将CheckedException包装在RuntimeException中不利于严格的错误处理。
它可以用作Java集合中使用的Consumer函数。
下面是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);
}
}));
}
这只是在重新抛出中包装lambda。它使CheckedException重新抛出在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;
}
}
在这里找到完整的代码和单元测试。