为什么Java泛型可以强制转换不可分配的类型(RuntimeExecution的每个异常)?

为什么Java泛型可以强制转换不可分配的类型(RuntimeExecution的每个异常)?,java,exception,generics,Java,Exception,Generics,我想知道为什么下面的代码可以工作: public static void throwUnchecked(Exception e) { TestGenericExceptionCast.<RuntimeException> doThrowUnchecked(e); } @SuppressWarnings("unchecked") private static <T extends Exception> void doThrowUnchecked(Exception

我想知道为什么下面的代码可以工作:

public static void throwUnchecked(Exception e) {
    TestGenericExceptionCast.<RuntimeException> doThrowUnchecked(e);
}

@SuppressWarnings("unchecked")
private static <T extends Exception> void doThrowUnchecked(Exception toThrow) throws T {
    throw (T) toThrow;
}

public static void main(String[] args) {
    throwUnchecked(new Exception());
}
为什么可以通过泛型将异常转换为RuntimeException

明白了:

根本不会发生强制转换,因为没有对象被指定给类型为T的对象

编译器被欺骗了,无法再看到它是一个已检查的异常。

因为,这意味着异常toThrow可以转换为t,即运行时异常

作为旁注,您可以通过执行以下操作来避免@SuppressWarnings:

@SuppressWarnings("unchecked")
private static <T extends Exception> void doThrowUnchecked(T toThrow) throws T {
    throw toThrow;
}
最后,在main方法中,您可以这样调用它:

public static void main(String[] args) {
    throwUnchecked(new RuntimeException());
}
此外,您可以通过将抛出的异常包装到RuntimeException来改进这一点:

把T抛到空中;并不真正将toThrow转换为RuntimeException。擦除后,类型绑定意味着实际发生的强制转换是throw Exception toThrow;,这很好用

但是,如果您将签名更改为:

private static <T extends RuntimeException> void doThrowUnchecked(Exception toThrow) throws T


这将把选中的异常包装在未选中的异常中。

您提到的代码在throwUnchecked方法中给出了一个编译错误。我不明白为什么关系RuntimeException extends异常应该用另一种方式表示强制转换。如果尝试强制转换RuntimeException而不是T,则会得到预期的ClassCastException。是否检查了throwUnchecked方法上的我的更新?:不,sry。throwUnchecked方法的更新在哪里?当使用非运行时异常(例如throwUncheckednew exception;)调用它时,此代码仍然抛出ClassCastException;。但现在这两种方法没有任何用处。您可以替换throwUncheckednew RuntimeException;通过抛出新的RuntimeException,它不会改变行为。在大多数情况下,这将很好地工作,但我的op是一个解决方案,可以在不包装异常的情况下取消选中异常。但我仍然不了解背后的机制:@BlackEye您不能将选中的异常类型转换为未选中的异常类型,就像您不能将动物引用转换为狗(如果它实际上是猫实例)一样。包装异常是我能想到的唯一方法。@BlackEye你说的工作良好是什么意思?它通过编译,但不会将传递的异常强制转换为RuntimeException。如果更改代码使其实际转换为RuntimeException,则在运行时将获得ClassCastException。它通过编译,但不会将传递的异常转换为RuntimeException。BlackEye所以基本上,你陷入了所有这些麻烦,只是为了欺骗编译器让你抛出一个选中的异常,而不在throws子句中声明它。首先抛出运行时异常不是更简单吗?有一个很好的理由说明为什么未处理的选中异常必须出现在throws子句中。这是一个很好的技巧。擦除。。。另见
public static <T extends Exception> void throwUnchecked(T toThrow) {
    throw new RuntimeException(toThrow);
}

public static void main(String[] args) throws Exception {
    throwUnchecked(new Exception());
}
private static <T extends RuntimeException> void doThrowUnchecked(Exception toThrow) throws T
throwUnchecked(new Exception());    
throw new RuntimeException (new Exception());