我知道如何创建一个有String参数并返回int的方法的引用,它是:
Function<String, Integer>
然而,如果函数抛出异常,比如它被定义为:
Integer myMethod(String s) throws IOException
我该如何定义这个引用呢?
我知道如何创建一个有String参数并返回int的方法的引用,它是:
Function<String, Integer>
然而,如果函数抛出异常,比如它被定义为:
Integer myMethod(String s) throws IOException
我该如何定义这个引用呢?
当前回答
我会做一些一般的事情:
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);
}
}
}
用法:
Lambda.handle(() -> method());
其他回答
如果你不介意使用第三方自由库(Vavr),你可以写
CheckedFunction1<String, Integer> f = this::myMethod;
它也有所谓的Try单子来处理错误:
Try(() -> f.apply("test")) // results in a Success(Integer) or Failure(Throwable)
.map(i -> ...) // only executed on Success
...
请在这里阅读更多。
声明:我是Vavr的创造者。
你可以。
扩展@marcg的UtilException,并在必要的地方添加泛型<E extends Exception>:这样,编译器将强制您再次添加抛出子句,一切就像您可以在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 { }
}
我所做的是允许用户在异常情况下给出他实际想要的值。 我有一个像这样的东西
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)
对我来说,首选的解决方案是使用Lombok。这是一个很好的图书馆。
而不是:
Integer myMethod(String s) throws IOException
你会有
import lombok.SneakyThrows;
@SneakyThrows
Integer myMethod(String s)
异常仍然被抛出,但您不需要使用throws声明它。
一些提供的解决方案使用E的泛型参数来传递抛出的异常类型。
更进一步,不是传递异常的类型,而是传递异常类型的Consumer,如……
Consumer<E extends Exception>
您可以创建几个Consumer<Exception>的可重用变体,这些变体将覆盖应用程序的常见异常处理需求。