Java8中的Lambda表达式

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

有人能帮我理解一下吗?我之前认为我们只能在Java 8中实现接口并覆盖其方法(用Lambda表达式替换匿名类)时使用Lambda表达式。

此外,在什么情况下会调用 invoke(Runnable r) 方法?

5个回答

8
在下一行中
String s = (String) invoke(() -> true);

实际上被调用的是invoke(Callable)方法。原因如下:

  • () -> true是一个零形式参数并返回结果的lambda表达式。
  • 这样的签名(零参数,单结果)与Callable接口的call()函数式方法兼容。请注意,该接口不需要具有@FunctionalInterface注释,只需具有单个抽象方法即可。
如果你想调用invoke(Runnable),你需要创建一个与接受零个参数并返回无结果的函数方法兼容的lambda表达式(即符合run()的签名)。像这样:
invoke(() -> System.out.println("foo"));

当运行时,它只会打印foo


8
一个lambda表达式提供了一个函数接口的实现。这就是你代码片段所做的事情。
你调用invoke传递了一个没有参数但返回一个值(在你的情况下是boolean)的lambda表达式。因此它匹配Object invoke(Callable c),而不是void invoke(Runnable r)(因为Callablecall方法有一个返回值,而Runnablerun方法没有返回值)。
invoke(() -> {System.out.println("something");});

由于在这种情况下lambda表达式没有返回类型,因此将调用void invoke(Runnable r)


7

只有在我们实现一个接口并重写它的方法时

基本上,这是你所做的。不是方法 s ,而是只有一个方法:call()。这个() -> true部分是您对 Callable#call()的实现。

换句话说,这行代码:

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

这个与这个是完全等价的:
String s = (String) invoke(new Callable() {
        @Override
        public Object call() throws Exception {
            return true;
        }
    });    

2
LambdaParameters -> LambdaBody

定义 lambda 函数的箭头操作符 (->)

  • Lambda: 仅用于执行后台任务(编译器会自动解析)
  • 表达式: 返回某种值

Lambda 表达式是另一种编写匿名类实例的方法,使得编写匿名类实例更容易。在 JVM 中,与使用 new 创建普通 Java 对象(执行静态变量、静态块、从整个层次结构加载类等)相比,它不会占用太多内存。

Lambda 表达式语法:

(params) -> expression to implement a @FunctionalInterface

在你的测试用例中:String s = (String) invoke(() -> true); 表达式返回类型为 true,没有参数。因此,Runnable FunctionalInterface 与 lambda 表达式不匹配,因为它具有 void run() 属性。它与 Callable FuncationalInterface 匹配,使用
V call()lambda 表达式的工作原理是什么?
它可能看起来像 lambda 表达式只是匿名内部类的语法糖,但是有一个更加优雅的方法。最简单的解释是:lambda 表达式由一个新方法表示,并且在运行时使用 invokedynamic 调用。 源代码:
class LambdaExample {

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

字节码等效:
class LambdaExample {

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

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

在JVM中,有一个lambda工厂可以从生成的lambda方法(例如lambda$1)创建功能接口(例如Runnable)的实例。
Lambda表达式非常棒,甚至在Java 8...中还有更多出色的功能。

我理解你的意思,但是不太明白字节码版本的含义! - Ashu
这并不是另一种创建匿名类的方式。在特定情况下,它更像是匿名类的替代品。 - shmosel

0

请看下面的例子。

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

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接