当前位置: 首页 > 面试题库 >

Java 8中异常类型推断的独特功能

周宏胜
2023-03-14
问题内容

在此站点上为另一个答案编写代码时,我遇到了这种特殊性:

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当未提及任何未经检查的异常类型时,它推断出什么可能的类型?

其次,接受这一工作原理后,为什么编译器会在nonSneakyThrow调用中抱怨?他们看起来非常相似。


问题答案:

的T
sneakyThrow推断为RuntimeException。可以从有关类型推断的语言规范(http://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html)中遵循此规则。

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

形式的边界throws α纯粹是信息性的:它指导分辨率优化α的实例化,因此,如果可能的话,它不是经过检查的异常类型。

这没有任何影响,但是它使我们指向了“解析”部分(18.4),该部分获得了有关特殊情况下的推断异常类型的更多信息:

......否则,如果绑定集包含throws αi,和α我的正常上限的,顶多ExceptionThrowableObject,然后TI = RuntimeException

这种情况适用于sneakyThrow-唯一的上限是Throwable,因此根据规范T推断为RuntimeException,因此可以编译。该方法的主体是无关紧要的-
未经检查的强制转换在运行时成功,因为它实际上并没有发生,从而留下了可以击败编译时检查的异常系统的方法。

nonSneakyThrow不会编译,因为该方法的T下限为Exception(即T必须是ExceptionException它本身的超类型),这是一个已检查的异常,这是由于调用该方法的类型而导致的,因此T推断为Exception



 类似资料:
  • 在这个网站上为另一个答案编写代码时,我遇到了这样一个特点: 首先,我很困惑为什么调用对编译器来说是可以的。当没有提到任何未检查的异常类型时,它推断出的可能类型是什么? 其次,既然这是可行的,那么编译器为什么要抱怨调用呢?他们看起来很像。

  • 主要内容:1 Java8 类型推断的介绍,2 Java8 类型推断的案例1,3 Java8 类型推断的案例21 Java8 类型推断的介绍 类型推断是Java的一项功能,它使编译器可以查看每个方法调用和相应的声明以确定参数的类型。 Java在Java 8中提供了类型推断的改进版本。 1.1 Java8以前 在下面的声明中,我们在一侧提到了arraylist的类型。这种方法是在Java 7中引入的。在这里,您可以将第二面留为<>,并且编译器将通过引用变量的类型来推断其类型。 1.2 Java8以后

  • 本文向大家介绍详谈Java8新特性泛型的类型推导,包括了详谈Java8新特性泛型的类型推导的使用技巧和注意事项,需要的朋友参考一下 1. 泛型究竟是什么?   在讨论类型推导(type inference)之前,必须回顾一下什么是泛型(Generic).泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。通俗点将就是“类型的变量”。这种类型变量可

  • 本文向大家介绍Java8中对泛型目标类型推断方法的改进,包括了Java8中对泛型目标类型推断方法的改进的使用技巧和注意事项,需要的朋友参考一下 一、简单理解泛型 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。通俗点将就是“类型的变量”。这种类型变量可以用在类、接口和方法的创建中。 理解Java泛型最简单的方法是把它看成一种便捷语法,能节省你

  • 我今天升级了一下... 我现在在v0上。2.11我在这个函数中遇到了一个奇怪的运行时错误: 我在没有任何参数的情况下调用函数,得到了子类型错误。 此代码在DartPad中工作。 有人知道会发生什么吗?