作家
登录

在Java中使用Lambda表达式的技巧

作者: 来源: 2017-08-10 14:43:18 阅读 我要评论

在本文中,我们将展示一些在 Java 8 中不太为人所懂得的 Lambda 表达式技能及其应用限制。本文的重要的受众是 Java 开辟人员,研究人员以及对象库的编写人员。 这里我们只会应用没有 com.sun 或其他内部类的公共 Java API,如斯代码就可以在不合的 JVM 实现之间进行移植。

结论很简单:

Lambda 表达式作为在 Java 8 中实现匿名办法的一种门路而被惹人,可以在某些场景中作为匿名类的替代筹划。 在字节码的层面上来看,Lambda 表达式被调换成了 invokedynamic 指令。如许的指令曾被用来创建功能接口的实现。 而单个方轨则是应用 Lambda 琅绫擎所定义的代码将调用宛转给实际办法。

例如,我们手头有如下代码:

这段代码被 Java 编译器翻译过来就成了下面如许:

invokedynamic 指令可以用 Java 代码粗略的表示成下面如许:

正如你所看见的,LambdaMetafactory 被用来生成一个调用站点,用目标办法句柄来表示一个工厂办法。这个工厂办法应用了 invokeExact 来返回功能接口的实现。如不雅 Lambda 封装了变量,则 invokeExact 会接收这些变量拿来作为实参。

在 Oracle 的 JRE 8 中,metafactory 会应用 ObjectWeb Asm 来动态地生成 Java 类,其实现了一个功能接口。 如不雅 Lambda 表达式封装了外部变量,生成的类琅绫擎就会有额外的域被添加进来。这种办法类似于 Java 说话中的匿名类 —— 然则有如下差别:

  • 匿名类是在编译时由 Java 编译器生成的。
  • Lambda 实现的类则是由 JVM 在运行时生成。

metafactory 的若何实现要看是什么 JVM 供给商和版本

在本文的后续内容中,我们将重点介绍 LambdaMetafactory 类及其功能。本文的下一节将假设你已经完全懂得了 metafactory 办法若何工作以及 MethodHandle 是什么。

在本节中,我们将介绍若何应用 lambdas 动态构建日常义务。

检查异常和 Lambdas

如不雅你想应用与 Java Streams 结合应用的 lambdas 内的检查异常的代码呢? 例如,我们须要将字符串列表转换成 URL 列表,如下所示:

URL(String)已经在 throws 处所声清楚明了一个检查的异常,是以它不克不及直接用作 Function 的办法引用。 

你说“是的,这里可以应用如许的技能”:

大年夜办法句柄构建 Lambdas

这是一个很挫的做法。原因如下:

  • 应用 try-catch 块
  • 从新抛出异常
  • Java 中类型擦除的应用不足

这个 bug 与 Java 编译器以及在 throws 部分声明泛型异常的才能有关。下面的示例代码演示了这种行动:

这个问题被应用以下方法可以更“合法”的方法解决:

  • 检查的异构造由 Java 编程说话的编译器辨认
  • throws 部分只是办法的元数据,在 JVM 级别没有语义含义
  • 检查和未检查的异常在字节码和 JVM 级别是弗成区分的

解决的办法是只把 Callable.call 的调用封装在不带 throws 部分的办法之中:

快速介绍

这段代码不会被 Java 编译器编译经由过程,因为办法 Callable.call 在其 throws 部分有受检异常。然则我们可以应用动态构造的 lambda 表达式擦除这个部分。

起首,我们要声明一个函数式接口,没有 throws 部分但可以或许委派调用给 Callable.call:

第二步是应用 LambdaMetafactory 创建这个接口的实现,以及委派 SilentInvoker.invoke 的办法调用给办法 Callable.call。如前所述,在字节码的级别上 throws 部分被忽视,是以,办法 SilentInvoker.invoke 可以或许调用办法 Callable.call 而无需声明受检异常:

第三,写一个实用办法,调用 Callable.call 而不声明受检异常:

如今,我们可以毫无顾忌地重写我们的流,应用异常检查:

此代码将成功编译,因为 callUnchecked 没有被声明为须要检查异常。此外,应用单态内联缓存时可以内联式调用此办法,因为在 JVM 中只有一个实现 SilentInvoker 接口的类。


  推荐阅读

  阿里云发布ECS企业级产品家族 19款实例族涵盖173个应用场景

为知足企业级客户对计算的高标准需求,8月9日,阿里云正式宣布云办事器ECS企业级产品家族,今朝已推出面向173种企业应用处景的19款实例。该系列合适在复杂的企业计算情况下,知足对于高机>>>详细阅读


本文标题:在Java中使用Lambda表达式的技巧

地址:http://www.17bianji.com/lsqh/36645.html

关键词: 探索发现

乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

网友点评
自媒体专栏

评论

热度

精彩导读
栏目ID=71的表不存在(操作类型=0)