Java 8 中异常类型推断的一个特殊特性 [英] A peculiar feature of exception type inference in Java 8

查看:19
本文介绍了Java 8 中异常类型推断的一个特殊特性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在为这个网站上的另一个答案编写代码时,我遇到了这个特点:

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

static void testSneaky() {
  final Exception e = new Exception();
  sneakyThrow(e);    //no problems here
  nonSneakyThrow(e); //ERRROR: Unhandled exception: java.lang.Exception
}

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

static <T extends Throwable> void nonSneakyThrow(T t) throws T {
  throw t;
}

首先,我很困惑为什么 sneakyThrow 调用对编译器来说是可以的.当没有提及任何未经检查的异常类型时,它为 T 推断出什么可能的类型?

First, I am quite confused why the sneakyThrow call is OK to the compiler. What possible type did it infer for T when there is no mention anywhere of an unchecked exception type?

其次,接受这可行,为什么编译器会抱怨 nonSneakyThrow 调用?他们看起来非常相似.

Second, accepting that this works, why then does the compiler complain on the nonSneakyThrow call? They seem very much alike.

推荐答案

sneakyThrow 的 T 被推断为 RuntimeException.这可以从关于类型推断的语言规范 (http://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html)

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)

首先,第 18.1.3 节中有一个注释:

Firstly, there's a note in section 18.1.3:

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

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.

这不会影响任何事情,但它为我们指明了解决方案部分 (18.4),该部分提供了有关具有特殊情况的推断异常类型的更多信息:

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:

... 否则,如果边界集包含throws αi,并且αi的正确上界至多为ExceptionThrowableObject,然后 Ti = RuntimeException.

... 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.

这种情况适用于 sneakyThrow - 唯一的上限是 Throwable,所以 T 被推断为 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 无法编译,因为该方法的 T 具有 Exception 的下限(即 T 必须是 Exception 的超类型,或 Exception 本身),这是一个已检查的异常,由于它被调用的类型,所以 T被推断为 Exception.

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.

这篇关于Java 8 中异常类型推断的一个特殊特性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆