Java Lambdas和闭包

我听说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在哪里键入? 或者他们不是(像一些奇怪的泛型)?
  • lambda是一种封闭类型,还是相反?
  • 这给我一个典型的匿名函数有什么好处?

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

    例如:

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

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

    因此,编译器可以安全地假定s1s2的类型是String

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

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

  • Lambda州。
  • Lambda图书馆版。
  • Lambda表达式的翻译
  • JVMLS 2012:在Java中实现Lambda表达式
  • 这第二篇文章解释了如何在字节码级别实现lambda表达式,并可能帮助您深入研究第二个问题的细节。


    请参阅本页以获得该示例的完整版本(但是,相关部分如下所示)。

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

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

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

    (x, y) => x + y
    

    对比如:

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

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


  • teamA和teamB在哪里键入? 或者他们不是(像一些奇怪的泛型)?
  • Lambda的使用目标类型,就像通用方法调用(自1.5)和钻石[不是]运算符(自1.7)一样。 粗略地说,应用了结果的类型用于提供单一抽象方法(SAM)基本类型的类型以及方法参数类型的类型(或可以推断)。

    作为1.5中通用方法推断的一个例子:

    Set<Team> noTeams = Collections.emptySet(); 
    

    1.7中的钻石操作员:

    Set<Team> aTeams = new HashSet<>();
    

    团队,团队,团队,团队,团队,团队。 我甚至爱说这个词团队。

  • lambda是一种封闭类型,还是相反?
  • lambda是一种有限的闭包形式,几乎和匿名内部类一样,但是有一些随机差异可以吸引你:

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

    为了弥补缺乏内在this ,如果直接分配到一个局部变量,则该值是拉姆达中访问。 IIRC(我可以检查,但不会),在一个匿名的内部类中,本地将处于作用域中,并将变量隐藏在外部作用域中,但不能使用它。 我相信缺少一个实例初始化程序使得这更容易指定。

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

  • 这给我一个典型的匿名函数有什么好处?
  • 简短的语法。 就是这样。

    当然,其余的Java语法也像以前一样绝望。

    我不认为这是在最初的实现中,而是作为[inner]类实现,而lambda可以使用方法句柄。 方法句柄的性能比之前的预测要差一些。 抛弃类,应该减少字节码的占用空间,可能的运行时间占用空间以及确定的类加载时间。 可能有一个实现,大多数匿名内部类(不是Serializable ,简单的静态初始化程序)没有经过构思不佳的类加载机制,没有发现任何特别明显的不兼容性。

    (希望我知道正确的术语。)

    链接地址: http://www.djcxy.com/p/51285.html

    上一篇: Java Lambdas and Closures

    下一篇: Does Java 8 Support Closures?