gpt4 book ai didi

java - 从 Java 语言的角度来看,trick with rethrow checked exceptions 是如何工作的?

转载 作者:行者123 更新时间:2023-11-30 06:47:20 27 4
gpt4 key购买 nike

我遇到过我必须在流表达式中捕获所有已检查的异常。我读过非常流行的话题:

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 中本地化了,因为下面的代码片段是正确的

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

最佳答案

Java 编译器理解 Class.forName()抛出一个checked异常。这需要以某种方式得到处理。但是当捕获那个checked 异常并让它看起来像是被包装到RuntimeException 中时例如 - 您解决了编译 问题。通过去掉编译器提示的“东西”。

请注意:编译器理解调用throwAsUnchecked(exception)总是呕吐。换句话说:通过在此处调用方法,该方法体内实际上没有必须抛出的代码。当然这不会改变运行时情况。最后,仍然抛出一个异常——令人惊讶的不是 RuntimeException,而是 ClassNotFoundException 的一个实例。

核心点是<E extends Throwable>转换为 RuntimeException(对于编译器)。那部分解释了here !

因此,foo() 的第二个版本可以这样写:

public void foo() { ...

不再需要声明throws ClassNotFoundException!

换句话说:这种方法的工作原理是“诱骗”编译器认为抛出的异常是未经检查的异常。这个技巧本身 Root 于泛型/类型删除。

关于java - 从 Java 语言的角度来看,trick with rethrow checked exceptions 是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46051037/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com