Home  >  Article  >  Java  >  In-depth understanding of Lambda expressions and functional interfaces

In-depth understanding of Lambda expressions and functional interfaces

青灯夜游
青灯夜游forward
2019-11-25 15:44:022085browse

Java8 is called the most changed version in the history of Java. It contains many important new features, the core of which is the addition of Lambda expressions and Stream API. The two can also be used together. [Recommended learning: java video tutorial]

In-depth understanding of Lambda expressions and functional interfaces

First let’s take a look at What is a Lambda expression.

Lambda expression, the explanation on Wikipedia is an operator used to represent anonymous functions and closures. I still feel that it is very abstract after seeing this explanation. Let's look at an example

public class SwingTest {
    public static void main(String[] args) {
        JFrame jFrame = new JFrame("My JFrame");
        JButton jButton = new JButton("My JButton");

        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {                
                System.out.println("Button Pressed!");
            } 
        }); 
        
        jFrame.add(jButton); jFrame.pack(); 
        jFrame.setVisible(true); 
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    }
}

This is a piece of code in Swing programming that binds a listening event to Button. When the Button is clicked, "Button Pressed!" will be output to the console. Here, an instance of an anonymous inner class is created to bind to the listener, which is also a more conventional code organization form in the past. But if we take a closer look, we will find that what we actually focus on is an ActionEvent type parameter e and the statement System.out.println("Button Pressed!"); output to the console.
If you replace the code that creates an interface instance as an anonymous inner class in the previous program with a Lambda expression, the code will be as follows
public class SwingTest {

public static void main(String[] args) {
    JFrame jFrame = new JFrame("My JFrame");
    JButton jButton = new JButton("My JButton");

    jButton.addActionListener(e -> System.out.println("Button Pressed!"));

    jFrame.add(jButton);
    jFrame.pack();
    jFrame.setVisible(true);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

}
Focus on the middle part The code change can be implemented in one line from the original 6 lines of code. This is a simple form of Lambda expression.
It can be seen that the syntax of Lambda expression is
(param1,param2,param3) -> {

//todo

}
The type program of the parameters here can be inferred based on the context, but it is not Not all types can be inferred. At this time, we need to explicitly declare the parameter type. When there is only one parameter, the parentheses can be omitted. When the todo section has only one line of code, the outer braces can be omitted. As in our example above

, in addition to concise code, have Lambda expressions brought us any changes?

Let’s recall that in Java, we cannot pass a function as a parameter to a method, nor can we declare that the return value is a function method. Before Java8, the answer was yes.

So, in the above example, we can actually pass a piece of code logic as a parameter to the listener, telling the listener that you can do this when the event is triggered, instead of using an anonymous inner class as an parameter. This is also another new feature brought by Java8: functional programming.

There are many languages ​​that support functional programming. In JavaScript, it is very common to pass a function as a parameter or the return value is a function. JavaScript is a very common functional language.

Lambda adds missing functional programming features to Java, allowing us to treat functions as first-class citizens.

In functional programming languages, the type of Lambda expression is a function. In Java, Lambda expressions are objects, and they must be attached to a special type of object-Functional Interface.

Next let’s look at the definition of functional interface:

If there is one and only one abstract method in an interface (methods in the Object class are not included), then this interface It can be regarded as a functional interface.

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

Let’s take a look at the declaration of the Runnable interface. After Java 8, the Runnable interface has an additional FunctionalInterface annotation, indicating that the interface is a functional interface. But if we do not add the FunctionalInterface annotation, if there is and is only one abstract method in the interface, the compiler will treat the interface as a functional interface.

@FunctionalInterface
public interface MyInterface {
    void test();
    String toString();
}

MyInterface This is also a functional interface, because toString() is a method in the Object class. It is just overridden here and will not increase the number of abstract methods in the interface.
(An additional mention here is that in Java8, the methods in the interface can not only have abstract methods, but also can have concrete implemented methods, which are called default methods. This part will be introduced in detail later. )
Since in Java, Lambda expressions are objects. So what is the type of this object? Let's review the SwingTest program again. Here, an ActionListener interface instance is created in the form of an anonymous inner class

jButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {                
        System.out.println("Button Pressed!");
    } 
});

After improvement using Lambda expression

jButton.addActionListener(e -> System.out.println("Button Pressed!"));

That is, we use Lambda expression to create an An example of the ActionListener interface. Let’s look at the definition of the ActionListener interface again.

public interface ActionListener extends EventListener {
    /**
     * Invoked when an action occurs.
     */
    public void actionPerformed(ActionEvent e);
}

There is only one abstract method. Although no FunctionalInterface annotation is added, it still conforms to the definition of a functional interface. The compiler will consider this to be a functional interface.
So, you can use Lambda expressions to create instances of functional interfaces. That is, the Lambda expression returns a functional interface type.

In fact, there are three ways to create functional interface instances (refer to the FunctionalInterface annotation):

1, Lambda expression

2, method reference (subsequent Chapter introduction)

3. Constructor method reference (subsequent chapter introduction)

Summary: In this article, we opened the door to learning Java8, learned what lambda expressions are, understood what the definition of functional interfaces is, and used several examples to demonstrate the convenience of lambda expressions.

For more related articles, please visit: java introductory learning

The above is the detailed content of In-depth understanding of Lambda expressions and functional interfaces. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete