Java8中的Lambda表达式

时间:2015-11-12 13:15:59

标签: java lambda java-8

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

任何人都可以帮我理解这个吗?我的印象是,只有当我们实现一个接口并覆盖它的方法(用Lambda表达式替换Anonymous类)时,我们才能在Java 8中使用lamba表达式。

同样在哪种情况下调用方法invoke(Runnable r)

5 个答案:

答案 0 :(得分:8)

在以下一行

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

实际上invoke(Callable)被调用了。原因是:

  • () -> true是一个lambda表达式,它具有零形式参数并返回结果。
  • 这样的签名(零参数,单个结果)与call()接口的功能方法Callable兼容。请注意,接口不需要@FunctionalInterface注释,只需要一个抽象方法。

如果要改为调用invoke(Runnable),则需要创建一个与函数方法兼容的lambda,该函数方法采用零参数并且不返回任何结果(即符合run()的签名) 。像这样:

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

在跑步时只打印foo

答案 1 :(得分:8)

lambda表达式提供了功能接口的实现。这就是您的代码段所做的事情。

您对invoke的调用传递的lambda表达式没有返回值的参数(在您的情况下为boolean)。因此,它与Object invoke(Callable c)匹配,而不是void invoke(Runnable r)(因为Callable call方法具有返回值,而Runnable' s run方法不会返回任何内容。

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

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

答案 2 :(得分:7)

  

仅当我们实现接口并覆盖其方法时

这或多或少都是你在这里所做的。不是方法 s ,而只是一种方法:() -> true。这个Callable#call()部分是您String s = (String) invoke(() -> true); 的实现。

换句话说,这一行:

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

完全等同于这个:

#server.R
library(shiny)
library(ggplot2)

shinyServer(function(input, output, session) {
  numberInput <- reactive({
    input$checkbox
  })

  lapply(1:10, function(i) {
    output[[paste0('b', i)]] <- renderPlot({
      qplot(x = rnorm(100, mean = as.numeric(numberInput()[i]))) +
        ggtitle(paste("This plot was plotted with", numberInput()[i], "option"))
    })
  })
})

#ui.R
library(shiny)    
shinyUI(fluidPage(
  title = 'lapply example',

  sidebarLayout(
    sidebarPanel(
      checkboxGroupInput("checkbox", "Checkbox",
                         choices = sample(1:10, 5))
    ),

    mainPanel(
      lapply(1:10, function(i) {
        plotOutput(paste0('b', i))
      })
    )
  )
))

答案 3 :(得分:0)

  • Lambda :只能用于执行后台任务(这里编译器然后计算出来)
  • 表达式:返回某种值

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

enter image description here

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...

中有更多优秀的东西

答案 4 :(得分: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);
}

}