A peculiar feature of exception type inference in Java 8

前端 未结 3 439
太阳男子
太阳男子 2020-11-29 19:00

While writing code for another answer on this site I came across this peculiarity:

static void testSneaky() {
  final Exception e = new Exception();
  sneaky         


        
3条回答
  •  囚心锁ツ
    2020-11-29 19:20

    The T of sneakyThrow is inferred to be RuntimeException. This can be followed from the langauge spec on type inference (http://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html)

    Firstly, there's a note in section 18.1.3:

    A bound of the form throws α is purely informational: it directs resolution to optimize the instantiation of α so that, if possible, it is not a checked exception type.

    This doesn't affect anything, but it points us to the Resolution section (18.4), which has got more information on inferred exception types with a special case:

    ... Otherwise, if the bound set contains throws αi, and the proper upper bounds of αi are, at most, Exception, Throwable, and Object, then Ti = RuntimeException.

    This case applies to sneakyThrow - the only upper bound is Throwable, so T is inferred to be RuntimeException as per the spec, so it compiles. The body of the method is immaterial - the unchecked cast succeeds at runtime because it doesn't actually happen, leaving a method that can defeat the compile-time checked exception system.

    nonSneakyThrow does not compile as that method's T has got a lower bound of Exception (ie T must be a supertype of Exception, or Exception itself), which is a checked exception, due to the type it's being called with, so that T gets inferred as Exception.

提交回复
热议问题