Description of lambda expression syntax in Java _java

Source: Internet
Author: User
Tags arithmetic serialization

Syntax description

A lambda expression consists of the following parts:

1. A comma-delimited list of formal parameters in parentheses. The Checkperson.test method contains an argument p that represents an instance of the person class. Note: The type of the parameter in a lambda expression can be omitted, and parentheses can be omitted if there is only one argument. For example, the code that was mentioned in the previous section:

  P-> p.getgender () = = Person.Sex.MALE
  && p.getage () >=
      && p.getage () <= 25

2. Arrow symbol:->. Used to separate parameters and function bodies.

3. Function body. Consists of an expression or a block of code. This expression is used in the example in the previous section:

P.getgender () = = Person.Sex.MALE
      && p.getage () >=
      && p.getage () <= 25

If you are using an expression, the Java runtime evaluates and returns the value of an expression. Alternatively, you can choose to use the return statement in the code block:

  P-> {return
    p.getgender () = = Person.Sex.MALE
        && p.getage () >=
        && p.getage () & Lt;=
  }

However, the return statement is not an expression. You need to enclose statements in curly braces in a lambda expression, but there is no need to enclose them in curly braces just to invoke a method that returns an empty value, so the following is true:

  Email-> System.out.println (email)

The Declaration of lambda expressions and methods looks like a lot of similar places. The lambda expression can also be treated as an anonymous method, which is a method that does not define a name.

The lambda expressions mentioned above are expressions that use only one parameter as a formal parameter. The following instance class, Caulator, demonstrates how to use more than one parameter as a formal parameter:

Package com.zhyea.zytools;

public class Calculator {

  interface Integermath {
    int operation (int a, int b);
  }

  public int operatebinary (int a, int B, Integermath op) {return
    op.operation (A, b);
  }

  public static void Main (String ... args) {
    Calculator myApp = new Calculator ();
    Integermath addition = (A, b)-> A + B;
    Integermath subtraction = (A, b)-> a-b;
    System.out.println ("+ 2 =" + Myapp.operatebinary (2, addition));
    System.out.println ("20-10 =" + myapp.operatebinary (M, subtraction));
  }


The Operatebinary method in the code uses two integer parameters to perform the arithmetic operation. The arithmetic operation here is itself an instance of the Integermath interface. A lambda expression is used in the above program to define two arithmetic operations: addition and subtraction. The execution program prints the following:

+ 2 =
20-10 = 10

Accessing local variables of external classes

Like a local class or an anonymous class, a lambda expression can also access local variables of an external class. In contrast, the use of lambda expressions does not require consideration of issues such as overrides. A lambda expression is just a lexical concept, which means that it does not need to inherit any names from the superclass or introduce new scopes. In other words, the declaration in a lambda expression is the same as the declaration meaning in its external environment. This is demonstrated in the following example:

Package com.zhyea.zytools;

Import Java.util.function.Consumer;

public class Lambdascopetest {public

  int x = 0;

  Class Firstlevel {public

    int x = 1;

    A statement with void Methodinfirstlevel (int x) {
      //below causes the compiler to error statement a at "local variables referenced from lambda expression mus T be final or effectively final "
      //x =;
      Consumer<integer> Myconsumer = (y)->{
        System.out.println ("x =" + x); Statement A
        System.out.println ("y =" + y);
        System.out.println ("this.x =" + this.x);
        System.out.println ("lambdascopetest.this.x =" + lambdascopetest.this.x);
      };

      Myconsumer.accept (x);
    }
  }

  public static void Main (String ... args) {
    Lambdascopetest st = new Lambdascopetest ();
    Lambdascopetest.firstlevel fl = st.new firstlevel ();
    Fl.methodinfirstlevel (%);
  }


This code will output the following:

x =
y =
this.x = 1 lambdascopetest.this.x =
0

If you replace an x with the parameter y in the lambda expression Myconsumer in the example, the compiler will complain:

  Consumer<integer> Myconsumer = (x)->{
        //...
      };

The compiler error message is: "variable x is already defined in method methodinfirstlevel (int)", which means that the variable x is already defined in the methods Methodinfirstlevel. The error is due to a lambda expression that does not introduce a new scope. Therefore, you can directly access the field fields, methods, and formal parameters of an external class in a lambda expression. In this example, the lambda expression Myconsumer directly accesses the formal parameter x of the method Methodinfirstlevel. You also use the This keyword directly when accessing members of an external class. In this example, this.x refers to firstlevel.x.

However, like a local class or an anonymous class, a lambda expression can only access local variables or members that are externally declared final (or equivalent to final). For example, we remove the comment before "x=99" in the example code Methodinfirstlevel method:

      The following statement causes the compiler to error statement a "Local variables referenced from a lambda expression must to be final or effectively final"
      X = the;
      Consumer<integer> Myconsumer = (y)->{
        System.out.println ("x =" + x); Statement A
        System.out.println ("y =" + y);
        System.out.println ("this.x =" + this.x);
        System.out.println ("lambdascopetest.this.x =" + lambdascopetest.this.x);
      };

Because the value of the parameter x is modified in this statement, the Methodinfirstlevel parameter x can no longer be considered final. So the Java compiler will quote a lambda expression that accesses local variable x, "local variables referenced from a lambda expression must to be final or effectively final "Such a mistake.

Target type

How do you judge the type of a lambda expression? Let's take a look at the code to screen age-appropriate military personnel:

   P-> p.getgender () = = Person.Sex.MALE
          && p.getage () >=
          && p.getage () <= 25

This code is used in two places:

public static void Printpersons (List<person> roster, Checkperson Tester)--Scenario Three
public void Printpersonswithpredicate (list<person> roster, predicate<person> Tester)--Programme VI

When calling the Printpersons method, this method expects an argument of the Checkperson type, at which point the expression above is an expression of the Checkperson type. When you call the Printpersonswithpredicate method, you expect an argument of the predicate<person> type, at which point the same expression is the predicate<person> type. Like this, the type to be determined by the type expected by the method is called the target type (in fact I think the type inference in Scala is more appropriate here). The Java compiler determines the type of a lambda expression by the context of the target type or by the location where the lambda expression is found. This means that lambda expressions can only be used where the Java compiler can infer a type:

    1. Variable declaration;
    2. assigning value;
    3. Return statement;
    4. Array initialization;
    5. method or constructor parameter;
    6. lambda expression method body;
    7. Conditional expression (? :);
    8. When an exception is thrown.

Target type and Method parameters

For method parameters, the Java compiler also relies on two language attributes to determine the target type: overload resolution and type parameter inference.

Look at the following two functional interfaces (Java.lang.Runnable and java.util.concurrent.callable<v>):

Public interface Runnable {
    void Run ();
  }

  Public interface Callable<v> {
    v call ();
  }

The Runnable.run () method has no return value and the Callable.call () method has.

Suppose we overload the Invoke method as follows:

 void Invoke (Runnable r) {
    r.run ();
  }

  <t> T Invoke (callable<t> c) {return
    c.call ();
  }

So which method will be called in the following statement:

String s = invoke(() -> "done");

Invoke Invoke (Callable<t>) because the method has a return value and Invoke (runnable<t>) does not return a value. In this case, the type of the lambda expression (()-> "Done") is callable<t>.

Serialization of

A lambda expression is serializable if the target type of a lambda expression and the type of the parameter it calls are serializable. However, as with inner classes, lambda expressions are strongly not recommended for serialization.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.