【问题标题】:Why doesn't Lombok.sneakyThrows throw a ClassCastException?为什么 Lombok.sneakyThrows 不抛出 ClassCastException?
【发布时间】:2021-11-01 14:10:37
【问题描述】:

我试图了解 Lombok 中的 @SneakyThrows 注释实际上是如何工作的。

this SO answer,我可以收集到它在后台使用Lombok.sneakyThrows() 方法。

Lombok.sneakyThrows()的代码如下:

public static RuntimeException sneakyThrow(Throwable t) {
    if (t == null) throw new NullPointerException("t");
    return Lombok.<RuntimeException>sneakyThrow0(t);
}

@SuppressWarnings("unchecked")
private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T {
    throw (T)t;
}

据我所知,它所做的只是将其转换为 java.lang.RuntimeException,因此编译器不会抱怨。

但这不应该在技术上给出ClassCastException吗?

例如:

public static void main(String args[]) {
    Throwable i = new InterruptedException();
    RuntimeException rr = (RuntimeException) i;
}

以上代码导致 ClassCastException。

那为什么龙目岛没有发生同样的事情呢?

【问题讨论】:

  • 您关于强制转换为 RuntimeException 的基本假设是错误的。请参阅文档。
  • 请参阅gamlor.info/wordpress/2010/02/…,其中详细介绍了此 hack。

标签: java generics exception lombok checked-exceptions


【解决方案1】:

请注意,这不是对RuntimeException 的强制转换,而是对泛型参数T 的强制转换,被限制为Throwable。由于Type Erasure,无法检查此演员表。演员是completely unchecked cast

运行时不知道T 是什么,除了extends Throwable。所以它无法检查t是否真的是T,如果不是则抛出异常。它所能做的就是检查t是否是Throwable,但t的类型已经是Throwable,所以也不需要这样做。

通常,您会看到有关此未经检查的强制转换的警告,这就是 @SuppressWarnings("unchecked") 所禁止的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 2013-04-12
    • 1970-01-01
    • 2015-08-10
    • 1970-01-01
    相关资源
    最近更新 更多