我知道如何创建一个有String参数并返回int的方法的引用,它是:

Function<String, Integer>

然而,如果函数抛出异常,比如它被定义为:

Integer myMethod(String s) throws IOException

我该如何定义这个引用呢?


当前回答

免责声明:我还没有使用过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;
}

其他回答

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

如果您不介意使用第三方库,使用cyclops-react(我贡献的一个库),您可以使用FluentFunctions API来编写

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

ofChecked接受jOOλ CheckedFunction,并将软化后的引用返回到标准(未选中)JDK java.util.function.Function。

或者,你可以通过FluentFunctions api继续使用捕获的函数!

例如,要执行你的方法,最多重试5次,并记录你可以写入的状态

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

您需要执行以下操作之一。

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

你可以。

扩展@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 { }
}

免责声明:我还没有使用过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;
}