
要留意 MethodHandleProxies 并非动态创建 lambda 表达式的幻想办法,因为这个类只是把 MethodHandle 封装到一个代劳类琅绫擎,然后把对 InvocationHandler.invoke 的调用指派给了 MethodHandle.invokeWithArguments 办法。 这种办法使得 Java 反射机制运行起来异常的慢。
如前所述,并不是所有的办法句柄都可以在运行时用于构建 lambdas。
只有几种与办法相干的办法句柄可以用于 lambda 表达式的动态构造
这包含:
- REF_invokeInterface: 对于接口办法可经由过程 Lookup.findVirtual 来构建
- REF_invokeVirtual: 对于由类供给的虚办法可以经由过程 Lookup.findVirtual 来构建
- REF_invokeStatic: 对于静态办法可经由过程 Lookup.findStatic 构建
- REF_newInvokeSpecial: 对于构造函数可经由过程 Lookup.findConstructor 构建
- REF_invokeSpecial: 对于私有办法和由类供给的早绑定的虚办法可经由过程 Lookup.findSpecial 构建
其他办法的句柄将会触发 LambdaConversionException 异常。
泛型异常
之所以会如许是因为 Java Stream 的管道只捕获到了一个原始类型,它是一个 Number 类。Number 类本身并没有实现 IntSupplier 接口。 要修复此问题,可以在一个作为办法引用的零丁办法中明白定义一个参数类型:

这段代码应当编译成功因为 URL 构造器抛出 MalformedURLException。但事实并非如斯。编译器产生以下缺点消息:

但如不雅我们用一个匿名类调换 lambda 表达式,那么代码就编译成功了:

当与 lambda 表达式合营应用时,泛型异常的类型揣摸不克不及精确工作。
泛型界线
一个带有多个界线的泛许可以用 & 号构造:<T extends A & B & C & ... Z>。这种泛型参数定义很少被应用,但因为其局限性,它对 Java 中的 lambda 表达示有某些影响:
- 每一个界线,除了第一个界线,都必须是一个接口。
- 具有这种泛型的类的原始版本只推敲了束缚中的第一个界线。
Lambdas 小技能
第二个局限性使 Java 编译器在编译时和 JVM 在运行时产生不合的行动,当 Lambda 表达式的联动产生时。可以应用以下代码重现此行动:

这段代码绝对没错,并且用 Java 编译器编译也会成功。MutableInteger 这个类可以知足泛型 T 的多个类型绑定束缚:
- MutableInteger 是大年夜 Number 持续的
- MutableInteger 实现了 IntSupplier
然则在运行的时刻会抛出异常:

经由过程 samMethodType 和 instantiatedMethodType(分别为办法 metafactory 的第三个和第五个参数)之间的差别,可以实现类型擦除后的函数接口中基于对象的参数和实际参数类型之间的主动转换以及 getter 或 setter 中的返回类型。实例化的办法类型是供给专门的 lambda 的办法实现。

这个示例就演示了 Java 编译器和运行时所进行的一次不精确的类型揣摸。
在 Java 中的编译时和运行时处理与 lambdas 浇忧⒛多个类型绑定会导致不兼容。
【编辑推荐】
- 在Node.js中应用MySQL&MySQL JavaScript客户端
- 20个异常有效的Java法度榜样片段
- 浅谈Java的Fork/Join并发框架
- 浅谈Java的Fork/Join并发框架
- JavaScript进阶之深刻懂得数据双向绑定
推荐阅读
阿里云发布ECS企业级产品家族 19款实例族涵盖173个应用场景
为知足企业级客户对计算的高标准需求,8月9日,阿里云正式宣布云办事器ECS企业级产品家族,今朝已推出面向173种企业应用处景的19款实例。该系列合适在复杂的企业计算情况下,知足对于高机>>>详细阅读
本文标题:在Java中使用Lambda表达式的技巧
地址:http://www.17bianji.com/lsqh/36645.html
1/2 1

网友点评
精彩导读
科技快报
品牌展示