Java Lambdas and Closures

I hear lambdas are coming soon to a Java near you (J8). I found an example of what they will look like on some blog:

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;
};

So right off the bat:

  • Where are teamA and teamB typed? Or aren't they (like some weird form of generics)?
  • Is a lambda a type of closure, or is it the other way around?
  • What benefits will this give me over a typical anonymous function?

  • The Lambda expression is just syntactic sugar to implement a target interface, this means that you will be implementing a particular method in the interface through a lambda expression. The compiler can infer the types of the parameters in the interface and that's why you do not need to explicitly define them in the lambda expression.

    For instance:

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

    In this expression, the lambda expression evidently implements a Comparator of strings, therefore, this implies the lambda expression is syntactic sugar for implementing compare(String, String) .

    Thus, the compiler can safely assume the type of s1 and s2 is String .

    Your target interface type provides all the information the compiler needs to determine what are the actual types of the lambda parameters.

    Briant Goetz, Java Language Architect at Oracle Corportion has published a couple of articles of the work in progress in JDK 8 Lambdas. I believe the answers to your questions are there:

  • State of Lambda.
  • State of Lambda Libraries Edition.
  • Translation of Lambda Expressions
  • JVMLS 2012: Implementing Lambda Expressions in Java
  • This second article explains how the lambda expressions are implemented at the bytecode level and may help you delve into the details of your second question.


    See this page for a full version of that example (however, the relevant parts are shown below).

    The types are inferred from the SoccerService interface and SoccerResult enum, not shown in your snippet:

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

    The benefit (of lambdas versus standard anonymous classes) is just reduced verbosity:

    (x, y) => x + y
    

    versus something like:

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

    For the difference between a closure and a lambda, see this question.


  • Where are teamA and teamB typed? Or aren't they (like some weird form of generics)?
  • Lambda's use target typing, much like generic method calls (since 1.5) and the diamond [not an] operator (since 1.7). Roughly, where the type the result applied to is stated (or can be inferred) that is used to supply the type of the Single Abstract Method (SAM) base type and hence the method parameter types.

    As an example of generic method inference in 1.5:

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

    And diamond operator in 1.7:

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

    Team, team, team, team, team, team. I even love saying the word team.

  • Is a lambda a type of closure, or is it the other way around?
  • A lambda is a limited form of closure in almost exactly the same way as anonymous inner classes, but with some random differences to catch you out:

    The outer this is not hidden by an inner this . This means that the same text in a lambda and an anonymous inner class can mean subtly but completely different things. That should keep Stack Overflow busy with odd questions.

    To make up for the lack of inner this , if assigned directly to a local variable, then that value is accessible within the lambda. IIRC (I could check, but wont), in an anonymous inner class the local will be in scope and hide variables in an outer scope but you can't use it. I believe the lack of an instance initialiser makes this much easier to specify.

    Local fields that do not happen to be marked final but could be, are treated as if they are final . So not are they in scope, but you can actually read (though not write) them.

  • What benefits will this give me over a typical anonymous function?
  • A briefer syntax. That's about it.

    Of course the rest of the Java syntax is just as hopelessly bad as ever.

    I don't believe this is in the initial implementation, but instead of being implemented as [inner] classes, lambdas can use method handles. The performance of method handles falls somewhat short of earlier predictions. Doing away with classes, should reduce bytecode footprint, possibly runtime footprint and certainly class loading time. There could be an implementation where most anonymous inner classes (not Serializable , trivial static initialiser) didn't go through the poorly conceived class loading mechanism without any particularly noticeable incompatibilities.

    (Hope I've got the terminology wrt hiding correct.)

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

    上一篇: functools.partial和类似的lambda之间的区别?

    下一篇: Java Lambdas和闭包