我知道如何创建一个有String参数并返回int的方法的引用,它是:
Function<String, Integer>
然而,如果函数抛出异常,比如它被定义为:
Integer myMethod(String s) throws IOException
我该如何定义这个引用呢?
我知道如何创建一个有String参数并返回int的方法的引用,它是:
Function<String, Integer>
然而,如果函数抛出异常,比如它被定义为:
Integer myMethod(String s) throws IOException
我该如何定义这个引用呢?
当前回答
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;
}
}
在这里找到完整的代码和单元测试。
其他回答
然而,你可以创建自己的FunctionalInterface,抛出如下..
@FunctionalInterface
public interface UseInstance<T, X extends Throwable> {
void accept(T instance) throws X;
}
然后使用Lambdas或引用实现它,如下所示。
import java.io.FileWriter;
import java.io.IOException;
//lambda expressions and the execute around method (EAM) pattern to
//manage resources
public class FileWriterEAM {
private final FileWriter writer;
private FileWriterEAM(final String fileName) throws IOException {
writer = new FileWriter(fileName);
}
private void close() throws IOException {
System.out.println("close called automatically...");
writer.close();
}
public void writeStuff(final String message) throws IOException {
writer.write(message);
}
//...
public static void use(final String fileName, final UseInstance<FileWriterEAM, IOException> block) throws IOException {
final FileWriterEAM writerEAM = new FileWriterEAM(fileName);
try {
block.accept(writerEAM);
} finally {
writerEAM.close();
}
}
public static void main(final String[] args) throws IOException {
FileWriterEAM.use("eam.txt", writerEAM -> writerEAM.writeStuff("sweet"));
FileWriterEAM.use("eam2.txt", writerEAM -> {
writerEAM.writeStuff("how");
writerEAM.writeStuff("sweet");
});
FileWriterEAM.use("eam3.txt", FileWriterEAM::writeIt);
}
void writeIt() throws IOException{
this.writeStuff("How ");
this.writeStuff("sweet ");
this.writeStuff("it is");
}
}
这个问题也一直困扰着我;这就是我创建这个项目的原因。
用它你可以做:
final ThrowingFunction<String, Integer> f = yourMethodReferenceHere;
JDK总共定义了39个接口,它们都有类似的抛出功能;这些都是流中使用的@ functionalinterface(基本流,还有IntStream, LongStream和DoubleStream)。
当它们中的每一个都扩展了它们的非抛出对应对象时,你也可以直接在lambdas中使用它们:
myStringStream.map(f) // <-- works
默认行为是,当您抛出lambda抛出一个检查异常时,抛出一个ThrownByLambdaException,并将检查异常作为原因。因此,您可以捕捉到它并得到原因。
其他特性也可用。
默认情况下,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;
};
并在调用者方法中添加抛出或尝试/捕获相同的异常。
一些提供的解决方案使用E的泛型参数来传递抛出的异常类型。
更进一步,不是传递异常的类型,而是传递异常类型的Consumer,如……
Consumer<E extends Exception>
您可以创建几个Consumer<Exception>的可重用变体,这些变体将覆盖应用程序的常见异常处理需求。
我是一个小库的作者,它具有一些通用的魔法,可以在任何地方抛出任何Java异常,而不需要捕获它们,也不需要将它们包装到RuntimeException中。
用法: unchecked(() -> methodThrowingCheckedException())
public class UncheckedExceptions {
/**
* throws {@code exception} as unchecked exception, without wrapping exception.
*
* @return will never return anything, return type is set to {@code exception} only to be able to write <code>throw unchecked(exception)</code>
* @throws T {@code exception} as unchecked exception
*/
@SuppressWarnings("unchecked")
public static <T extends Throwable> T unchecked(Exception exception) throws T {
throw (T) exception;
}
@FunctionalInterface
public interface UncheckedFunction<R> {
R call() throws Exception;
}
/**
* Executes given function,
* catches and rethrows checked exceptions as unchecked exceptions, without wrapping exception.
*
* @return result of function
* @see #unchecked(Exception)
*/
public static <R> R unchecked(UncheckedFunction<R> function) {
try {
return function.call();
} catch (Exception e) {
throw unchecked(e);
}
}
@FunctionalInterface
public interface UncheckedMethod {
void call() throws Exception;
}
/**
* Executes given method,
* catches and rethrows checked exceptions as unchecked exceptions, without wrapping exception.
*
* @see #unchecked(Exception)
*/
public static void unchecked(UncheckedMethod method) {
try {
method.call();
} catch (Exception e) {
throw unchecked(e);
}
}
}
来源:https://github.com/qoomon/unchecked-exceptions-java