调用引发泛型异常的泛型方法时出现编译错误

问题描述 投票:0回答:1

我正在编译这个类:

public class Test {

    // No throws clause here
    public static void main(String[] args) {
        doThrow(new SQLException());
    }

    static void doThrow(Exception e) {
        Test.<Exception>doThrow0(e);
        Test.doThrow0(e);
    }


    static <E extends Exception> void doThrow0(Exception e) throws E {
        throw (E) e;
    }
}

为什么

**Test.<Exception>doThrow0(e);**
这一行给出错误来指定 throws 子句(或将其包含在 try-catch 中) 并且
**Test.doThrow0(e);**
此行不会给出使用 throws 子句的任何错误

java exception checked-exceptions
1个回答
1
投票

这是因为类型推断更喜欢尽可能推断出现在

throws
子句中的类型参数而不是未经检查的异常。

来自JLS 18.1.3

在推理过程中,维护一组推理变量的界限。界限具有以下形式之一:

  • ...
  • throws α
    :推理变量 α 出现在
    throws
    子句中。

...

throws α
形式的界限纯粹是信息性的:它指导解析来优化 α 的实例化,以便在可能的情况下,它不是受检查的异常类型。

在第一次尝试分辨率时,考虑了这个界限。

否则,如果边界集包含

throws αi
,并且 αi 的每个真上界都是
RuntimeException
的超类型,则 Ti =
RuntimeException

Test.doThrow0(e)
中,没有任何内容表明
E
应该是受检异常,因此类型推断将其推断为
RuntimeException
,即未经受检异常。

如果

doThrow0
采用
E
作为参数,则会在参数类型和
doThrow0
抛出的异常类型之间建立关系。现在
E
将在调用
Exception
中被推断为
Test.doThrow0(e)

Test<Exception>doThrow0(e)
中,您明确指定
E
应该是受检查的异常。这里甚至不涉及类型推断。

另请参阅这个其他问题,您可以在其中找到需要“尝试不推断已检查异常”的示例。

© www.soinside.com 2019 - 2024. All rights reserved.