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

Function<String, Integer>

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

Integer myMethod(String s) throws IOException

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


当前回答

你可以使用ET。ET是一个用于异常转换/转换的小型Java 8库。

对于ET,它看起来是这样的:

// 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实例是线程安全的,可以由多个组件共享。如果你喜欢,你可以配置更具体的异常转换规则(例如FooCheckedException -> BarRuntimeException)。 如果没有其他可用的规则,被检查的异常将自动转换为RuntimeException。

(声明:我是ET的作者)

其他回答

如果你有lombok,你可以用@SneakyThrows注释你的方法

SneakyThrow不会静默地吞咽、包装到RuntimeException中,或以其他方式修改所列出的检查异常类型的任何异常。JVM不检查被检查异常系统的一致性;Javac可以,而且这个注释允许您选择不使用它的机制。

https://projectlombok.org/features/SneakyThrows

这并不是Java 8所特有的。你正在尝试编译一些等价的东西:

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

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

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

我所做的是允许用户在异常情况下给出他实际想要的值。 我有一个像这样的东西

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)

我使用一个名为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);
        }
    }
}