我非常感谢有关lambda和默认方法接口的Java 8新功能。但是,我仍然对检查的异常感到无聊。例如,如果我只想列出对象的所有可见字段,我想简单地写一下:
Arrays.asList(p.getClass().getFields()).forEach(
f -> System.out.println(f.get(p))
);
但是,由于该get
方法可能会抛出一个与Consumer
接口协定不同的已检查异常,所以我必须捕获该异常并编写以下代码:
Arrays.asList(p.getClass().getFields()).forEach(
f -> {
try {
System.out.println(f.get(p));
} catch (IllegalArgumentException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
);
但是,在大多数情况下,我只希望将异常作为a抛出,RuntimeException
并让程序处理或不处理没有编译错误的异常。
因此,我想就我对有争议的异常进行检查的方法发表您的看法。为此,我创建了一个辅助接口ConsumerCheckException<T>
和一个实用程序功能rethrow
(根据Doval的评论进行了更新),如下所示:
@FunctionalInterface
public interface ConsumerCheckException<T>{
void accept(T elem) throws Exception;
}
public class Wrappers {
public static <T> Consumer<T> rethrow(ConsumerCheckException<T> c) {
return elem -> {
try {
c.accept(elem);
} catch (Exception ex) {
/**
* within sneakyThrow() we cast to the parameterized type T.
* In this case that type is RuntimeException.
* At runtime, however, the generic types have been erased, so
* that there is no T type anymore to cast to, so the cast
* disappears.
*/
Wrappers.<RuntimeException>sneakyThrow(ex);
}
};
}
/**
* Reinier Zwitserloot who, as far as I know, had the first mention of this
* technique in 2009 on the java posse mailing list.
* http://www.mail-archive.com/javaposse@googlegroups.com/msg05984.html
*/
public static <T extends Throwable> T sneakyThrow(Throwable t) {
throw (T) t;
}
}
现在我可以写:
Arrays.asList(p.getClass().getFields()).forEach(
rethrow(f -> System.out.println(f.get(p)))
);
我不确定这是否是克服检查异常的最佳方法,但是正如我所解释的,我希望有一种更方便的方式来实现我的第一个示例,而无需处理检查异常,这是我发现的更简单的方法去做吧。
sneakyThrow
在内部使用rethrow
引发经过检查的原始异常,而不必将其包装在中RuntimeException
。或者,您可以使用Project Lombok中的@SneakyThrows
注释执行相同的操作。
Consumer
s in 。与消费者一起引发的可抛出异常将传播到调用线程,该线程1)不会停止其他同时运行的消费者,这可能是适当的,也可能是不合适的; 2)如果一个以上的消费者抛出了某些东西,则仅调用线程将看到其中之一。forEach
Stream