Java Lambdas和Closures

我听说lambdas即将到达你附近的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; }; 

所以马上就是这样:

  • teamAteamB在哪里打字? 或者不是它们(就像一些奇怪的generics)?
  • lambda是一种闭包,还是反过来?
  • 这会给我一个典型的匿名function有什么好处?

Lambda表达式只是实现目标接口的语法糖,这意味着您将通过lambda表达式在接口中实现特定方法。 编译器可以推断接口中参数的类型,这就是您不需要在lambda表达式中显式定义它们的原因。

例如:

 Comparator c = (s1, s2) -> s1.compareToIgnoreCase(s2); 

在这个表达式中,lambda表达式显然实现了字符串的Comparator ,因此,这意味着lambda表达式是用于实现compare(String, String)语法糖。

因此,编译器可以安全地假设s1的类型和s2String

目标接口类型提供编译器确定lambda参数的实际类型所需的所有信息。

Oracle Corportion的Java语言架构师Briant Goetz在JDK 8 Lambdas上发表了一些正在进行的工作。 我相信你的问题的答案是:

  • Lambda州 。
  • Lambda Libraries Edition 。
  • Lambda表达式的翻译
  • JVMLS 2012:使用Java实现Lambda表达式

第二篇文章解释了如何在字节码级别实现lambda表达式,并可以帮助您深入研究第二个问题的细节。

有关该示例的完整版本,请参阅此页面 (但相关部分如下所示)。

这些类型是从SoccerService接口和SoccerResult枚举中推断出来的,未在您的代码段中显示:

 enum SoccerResult{ WON, LOST, DRAW } interface SoccerService { SoccerResult getSoccerResult(Integer teamA, Integer teamB); } 

(lambda与标准匿名 )的好处只是减少了冗长:

 (x, y) => x + y 

与之类似:

 new Adder() { public int add(int x, int y) { return x + y; } } 

对于闭包和lambda之间的区别,请参阅此问题 。

  • teamA和teamB在哪里打字? 或者不是它们(就像一些奇怪的generics)?

Lambda使用目标类型,非常类似于generics方法调用(从1.5开始)和菱形[不是]运算符(从1.7开始)。 粗略地说,用于提供单抽象方法(SAM)基类型的类型并因此提供方法参数类型的结果所应用的类型(或可以推断)。

作为1.5中generics方法推理的一个例子:

 Set noTeams = Collections.emptySet(); 

和钻石运营商在1.7:

 Set aTeams = new HashSet<>(); 

团队,团队,团队,团队,团队,团队。 我甚至喜欢说团队这个词。

  • lambda是一种闭包,还是反过来?

lambda是一种有限forms的闭包,与匿名内部类几乎完全相同,但有一些随机差异可以解决你:

外部this不是内在的隐藏。 这意味着lambda和匿名内部类中的相同文本可能意味着微妙但完全不同的东西。 那应该让Stack Overflow忙于奇怪的问题。

为了弥补内在的缺失,如果直接分配给局部变量,则可以在lambda中访问该值。 IIRC(我可以检查,但不会),在一个匿名内部类中,本地将在范围内并在外部范围中隐藏变量但您不能使用它。 我认为缺少实例初始化器使得更容易指定。

本地字段不会被标记为final但可能被标记为final 。 所以它们不在范围内,但你实际上可以阅读(尽管不是写)它们。

  • 这会给我一个典型的匿名function有什么好处?

更简洁的语法。 就是这样。

当然,Java语法的其余部分和以前一样毫无希望。

我不相信这是在初始实现中,但不是作为[内部]类实现,lambdas可以使用方法句柄。 方法句柄的性能略低于早期的预测。 废除类,应该减少字节码占用空间,可能减少运行时占用空间和类加载时间。 可能存在一种实现,其中大多数匿名内部类(不是Serializable ,普通的静态初始化器)没有通过构思不良的类加载机制而没有任何特别明显的不兼容性。

(希望我的术语听起来是正确的。)