简体   繁体   English

Java8 中的 Lambda 表达式

[英]Lambda Expressions in Java8

import java.util.concurrent.Callable;

public class AdvancedLambda {

    static void invoke(Runnable r){
        r.run();
    }

    static Object invoke(Callable c) throws Exception {
        return c.call();
    }

    public static void main(String[] args) throws Exception {

        String s = (String) invoke(() -> true);
        System.out.println(s);
    }
}

Can anyone help me understand this?任何人都可以帮助我理解这一点吗? I was under the impression that we can only use lamba expressions in Java 8 only when we implement an interface and override its methods (replacing Anonymous classes by Lambda expressions).我的印象是,只有在实现接口并覆盖其方法(用 Lambda 表达式替换匿名类)时,我们才能在 Java 8 中使用 Lamba 表达式。

Also in which situation will the method invoke(Runnable r) be called?还有在什么情况下会invoke(Runnable r)方法?

In the following line在以下行中

String s = (String) invoke(() -> true);

It is actually invoke(Callable) that is getting called.它实际上是被invoke(Callable) The reason is:原因是:

  • () -> true is a lambda expression that has zero formal parameter and return a result. () -> true是一个形式参数为零并返回结果的 lambda 表达式。
  • Such a signature (zero parameter, single result) is compatible with the functional method call() of the Callable interface.这样的签名(零参数,单一结果)与Callable接口的函数方法call()兼容。 Note that the interface does not need to have the @FunctionalInterface annotation, it just needs to have a single abstract method.请注意,接口不需要有@FunctionalInterface注释,它只需要有一个抽象方法。

If you want to invoke invoke(Runnable) instead, you will need to create a lambda that is compatible with a functional method that takes zero parameter and returns no result (ie conforms with the signature of run() ).如果要改为调用invoke(Runnable) ,则需要创建一个与采用零参数且不返回结果的函数式方法兼容的 lambda(即符合run()的签名)。 Something like this:像这样的东西:

invoke(() -> System.out.println("foo"));

Which just prints foo when ran.运行时只打印foo

A lambda expression supplies an implementation for a functional interface.一个 lambda 表达式提供了一个函数式接口的实现。 This is what your code snippet does.这就是您的代码片段所做的。

Your call to invoke passes a lambda expression with no arguments that returns a value (a boolean in your case).您对invoke传递了一个不带参数的 lambda 表达式,该表达式返回一个值(在您的情况下为boolean )。 Therefore it matches Object invoke(Callable c) , and not void invoke(Runnable r) (since a Callable 's call method has a return value while a Runnable 's run method doesn't return anything).因此它匹配Object invoke(Callable c) ,而不是void invoke(Runnable r) (因为Callablecall方法有一个返回值,而Runnablerun方法不返回任何东西)。

invoke(() -> {System.out.println("something");});

will call void invoke(Runnable r) , since in this case the lambda expression has no return type.将调用void invoke(Runnable r) ,因为在这种情况下 lambda 表达式没有返回类型。

only when we Implement a interface and override its methods只有当我们实现一个接口并覆盖它的方法时

That's, more or less, what you do here.这或多或少就是你在这里所做的。 Not method s , but just one method: call() .不是方法s ,而是一种方法: call() This () -> true part is your implementation of Callable#call() .这个() -> true部分是你对Callable#call()

In other words, this line:换句话说,这一行:

String s = (String) invoke(() -> true);

would be totally equivalent with this one:将完全等同于这个:

String s = (String) invoke(new Callable() {
        @Override
        public Object call() throws Exception {
            return true;
        }
    });    
LambdaParameters -> LambdaBody

The arrow operator ( -> ) for defining lambda functions用于定义 lambda 函数的箭头运算符 ( -> )

  • Lambda :can only be used to execute background tasks (here compiler then figures out) Lambda : 只能用于执行后台任务(这里编译器自己计算)
  • Expressions : are return a value of some kind表达式:返回某种值

Lambda expression is another way of writing an instance of anonymous class, to make an instance of anonymous class easier to write. Lambda 表达式是另一种编写匿名类实例的方式,使匿名类的实例更易于编写。 In JVM, it will not occupy much memory as comparing with normal java object creation with new (executing static variables, static blocks, loading classes from whole hierarchy ).在JVM中,与使用new (执行静态变量,静态块,从整个层次结构加载类)的普通java对象创建相比,它不会占用太多内存。

Lambda expression syntax: Lambda 表达式语法:

(params) -> expression to implement a @FunctionalInterface

In your test case: String s = (String) invoke(() -> true);在您的测试用例中: String s = (String) invoke(() -> true); the expression has return type true with no argument.表达式的返回类型为true ,没有参数。 So the Runnable FunctionalInterface does not match with lambda expression because it has void run() attribute.因此Runnable FunctionalInterface与 lambda 表达式不匹配,因为它具有void run()属性。 It matches with Callable FuncationalInterface using它与Callable FuncationalInterface匹配使用
V call() . V call()

How lambda expressions work under the hood? lambda 表达式在底层是如何工作的?
It might look like the lambda expressions are just the syntax sugar for anonymous inner classes, but there is much more elegant approach.看起来 lambda 表达式只是匿名内部类的语法糖,但还有更优雅的方法。 The simplest explanation is: the lambda expression is represented by a new method, and it is invoked at run-time using invokedynamic.最简单的解释是: lambda 表达式由一个新方法表示,并在运行时使用invokedynamic调用。

Source Code:源代码:

class LambdaExample {

    public void abc() {
        Runnable r = () -> { 
            System.out.println("hello");
        }
        r.run();
    }
    
}

Bytecode equivalent:字节码等效:

class LambdaExample {

    public void abc() {
        Runnable r = <lambda$1 as Runnable instance>;
        r.run(); 
    }

    static void lambda$1() {
        System.out.println("hello");
    }
    
}

Inside the JVM, there is a lambda factory that creates an instance of the functional interface (eg Runnable) from the generated lambda method (eg lambda$1).在 JVM 内部,有一个 lambda 工厂,它根据生成的 lambda 方法(例如 lambda$1)创建功能接口(例如 Runnable)的实例。

Lambda expressions are great, and there's even more great stuff in Java 8... Lambda 表达式很棒, Java 8 中还有更多很棒的东西......

Take a look at below example.看看下面的例子。

import javafx.beans.DefaultProperty;
import jdk.nashorn.internal.codegen.CompilerConstants;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * Created by KUMAJYE on 13/09/2016.
 */
public class ThreadMonitor {

private static int noOfThreads = 0;


public static void main(String[] args) {
    ThreadModel threadModel;
    noOfThreads = Integer.parseInt(args[0]);
    if (noOfThreads > 0) {
        threadModel = getThreadingModelForCallsInCallingThread();
    } else {
        threadModel = getAsynchThreadingModel();
    }

}

public static ThreadModel getThreadingModelForCallsInCallingThread() {
    ExecutorService executor = Executors.newFixedThreadPool(noOfThreads);
    return (r) -> executor.submit(r);
}


public static ThreadModel getAsynchThreadingModel() {
    // do execution on same Thread or separate Thread.
    // or
    // r.run();
    return (r) -> new Thread(r).start();
}

interface ThreadModel {

    void invoke(Runnable r);
}

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM