Java Lambdas和闭包
我听说Lambda很快就要来到你附近的Java(J8)。我在某个博客上找到了一个它们的样子示例:
SoccerService soccerService = (teamA, teamB) -> {
SoccerResult result = null;
if (teamA == teamB) {
result = SoccerResult.DRAW;
}
else if(teamA < teamB) {
result = SoccerResult.LOST;
}
else {
result = SoccerResult.WON;
}
return result;
};
所以马上:
teamA
和teamB
在哪里键入?或者它们不是(像某种奇怪的泛型)李>- lambda是闭包的类型,还是相反李>
- 与典型的匿名函数相比,这会给我带来什么好处李>
# 1 楼答案
Lambda表达式只是实现目标接口的语法糖,这意味着您将通过Lambda表达式实现接口中的特定方法。编译器可以推断接口中参数的类型,这就是为什么不需要在lambda表达式中显式定义它们
例如:
在这个表达式中,lambda表达式显然实现了
Comparator
个字符串,因此,这意味着lambda表达式是实现compare(String, String)
的语法糖因此,编译器可以安全地假定
s1
和s2
的类型为String
目标接口类型提供编译器确定lambda参数的实际类型所需的所有信息
OracleCorparty的Java语言架构师BriantGoetz发表了两篇关于JDK8Lambdas中正在进行的工作的文章。我相信你的问题的答案是:
第二篇文章解释了lambda表达式是如何在字节码级别实现的,并可能帮助您深入了解第二个问题的细节
# 2 楼答案
有关该示例的完整版本,请参见this page(不过,相关部分如下所示)
这些类型是从SoccerService接口和SoccerResult枚举推断出来的,不会显示在代码段中:
lambdas与标准匿名类相比的好处在于减少了冗长性:
而不是像:
有关闭包和lambda之间的区别,请参见this question
# 3 楼答案
Lambda使用目标类型,很像泛型方法调用(自1.5起)和菱形运算符(自1.7起)。粗略地说,其中说明(或可以推断)应用结果的类型,该类型用于提供单一抽象方法(SAM)基类型的类型,从而提供方法参数类型
作为1.5中通用方法推断的示例:
和1.7中的菱形运算符:
团队,团队,团队,团队,团队,团队,团队。我甚至喜欢说团队这个词
lambda是一种有限形式的闭包,其方式与匿名内部类几乎完全相同,但存在一些随机差异:
外部
this
不被内部this
隐藏。这意味着lambda和匿名内部类中的相同文本可能意味着微妙但完全不同的事物。这将使堆栈溢出忙于处理奇怪的问题为了弥补内部
this
的不足,如果直接指定给局部变量,则该值可以在lambda中访问。IIRC(我可以检查,但不会),在一个匿名的内部类中,局部变量将位于作用域中,并将变量隐藏在外部作用域中,但您不能使用它。我相信由于缺少实例初始化器,因此更容易指定没有标记
final
但可以标记的本地字段被视为final
。所以它们不在范围内,但实际上您可以读取(尽管不写入)它们更简洁的语法。就这样
当然,Java语法的其余部分和以往一样糟糕得令人绝望
我不相信这是在最初的实现中,但是lambdas可以使用方法句柄,而不是作为[internal]类实现。方法句柄的性能在某种程度上低于早期的预测。去掉类,应该减少字节码占用,可能会减少运行时占用,当然还有类加载时间。可能存在这样一种实现:大多数匿名内部类(不是
Serializable
,普通的静态初始化器)没有经过构思糟糕的类加载机制,没有任何特别明显的不兼容性(希望我的术语wrthiding是正确的。)