Java Lambdas和Closures

IAm*_*aja 20 java lambda closures java-8

我听说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;
};
Run Code Online (Sandbox Code Playgroud)

所以马上就开始了:

  • 在哪里teamAteamB类型?或者不是它们(就像一些奇怪的泛型)?
  • lambda是一种闭包,还是相反?
  • 这会给我一个典型的匿名函数带来什么好处?

DNA*_*DNA 15

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

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

enum SoccerResult{
    WON, LOST, DRAW
}

interface SoccerService {
    SoccerResult getSoccerResult(Integer teamA, Integer teamB);
}
Run Code Online (Sandbox Code Playgroud)

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

(x, y) => x + y
Run Code Online (Sandbox Code Playgroud)

与之类似:

new Adder()
{
  public int add(int x, int y)
  {
    return x + y;
  }
}
Run Code Online (Sandbox Code Playgroud)

有关闭包和lambda之间的区别,请参阅此问题.


Edw*_*rzo 15

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

例如:

Comparator<String> c = (s1, s2) -> s1.compareToIgnoreCase(s2);
Run Code Online (Sandbox Code Playgroud)

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

因此,编译器可以安全地假定的类型s1s2String.

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

Oracle Corportion的Java语言架构师Briant Goetz发表了几篇关于JDK 8 Lambdas正在进行的工作的文章.我相信你的问题的答案是:

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

  • "Lambda表达式只是实现目标接口的语法糖" - 不,它不是.在这种情况下,它们必然是内部类的语法糖.Java语言作者明确指出**lambdas*不仅仅是*内部类的语法糖**!Lambdas是一流的结构. - http://www.oracle.com/events/us/en/java8/index.html 7:30分钟 (2认同)

Tom*_*ine 9

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

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

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

Set<Team> noTeams = Collections.emptySet(); 
Run Code Online (Sandbox Code Playgroud)

和钻石运营商在1.7:

Set<Team> aTeams = new HashSet<>();
Run Code Online (Sandbox Code Playgroud)

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

  • lambda是一种闭包,还是相反?

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

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

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

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

  • 这会给我一个典型的匿名函数带来什么好处?

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

当然,Java语法的其余部分和以前一样无可救药.

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

(希望我已经得到了术语WRT 隐藏正确的.)