【发布时间】:2017-09-05 09:04:18
【问题描述】:
我遇到过我必须在流表达式中捕获所有已检查的异常。 我读过非常热门的话题:
How can I throw CHECKED exceptions from inside Java 8 streams?
并且有以下方法的答案:
我们有 3 个字符串:
"java.lang.Object"
"java.lang.Integer"
"java.lang.Strin"
我们想按名称加载类。
因此我们需要使用Class#forName方法
Class#forName java doc)
如您所见,以下方法声明包含
throws ClassNotFoundException
因此,如果我们使用通常的循环,我们需要编写以下代码:
public void foo() throws ClassNotFoundException {
String arr[] = new String[]{"java.lang.Object", "java.lang.Integer", "java.lang.Strin"};
for(String className:arr){
Class.forName(className);
}
}
让我们尝试使用流重写它:
public void foo() throws ClassNotFoundException {
String arr[] = new String[]{"java.lang.Object", "java.lang.Integer", "java.lang.Strin"};
Stream.of(arr).forEach(Class::forName);
}
编译器说:
Error:(46, 32) java: incompatible thrown types java.lang.ClassNotFoundException in method reference
好的,让我们尝试使用上述主题的方法:
我们创建以下方法:
public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) {
return t -> {
try {
consumer.accept(t);
} catch (Exception exception) {
throwAsUnchecked(exception);
}
};
}
@FunctionalInterface
public interface Consumer_WithExceptions<T, E extends Exception> {
void accept(T t) throws E;
}
@SuppressWarnings("unchecked")
private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E {
throw (E) exception;
}
客户端代码如下所示:
public void foo() throws ClassNotFoundException {
String arr[] = new String[]{"java.lang.Object", "java.lang.Integer", "java.lang.Strin"};
Stream.of(arr).forEach(rethrowConsumer(Class::forName));
}
我想知道它是如何工作的。这对我来说真的不清楚。
让我们研究rethrowConsumer:
public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) {
return t -> {
try {
consumer.accept(t);
} catch (Exception exception) {
throwAsUnchecked(exception);
}
};
}
和 throwAsUnchecked 签名看起来很像
private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E {
请澄清这个烂摊子。
附言
我将魔法发生在 throwAsUnchecked 中,因为遵循 sn-p 正确
public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) {
return t -> {
try {
throw new Exception();
} catch (Exception exception) {
throwAsUnchecked(exception);
}
};
}
但不跟随
public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) {
return t -> {
try {
consumer.accept(t);
} catch (Exception exception) {
throw new Exception();
//throwAsUnchecked(exception);
}
};
}
【问题讨论】:
-
仅作记录:您只使用“_”表示 SOME_CONSTANT。它不会进入任何其他类型的名称。
-
@GhostCat 它是来自链接主题的复制粘贴
-
@GhostCat 实际上我不明白为什么编译器将 Throwable 解释为 RuntimeException
-
这可以在我的回答中的链接问题中找到。具体来说,您想阅读以下内容:stackoverflow.com/a/14039011/1531124
标签: java generics exception-handling java-stream checked-exceptions