[英]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);
}
}
任何人都可以幫助我理解這一點嗎? 我的印象是,只有在實現接口並覆蓋其方法(用 Lambda 表達式替換匿名類)時,我們才能在 Java 8 中使用 Lamba 表達式。
還有在什么情況下會invoke(Runnable r)
方法?
在以下行中
String s = (String) invoke(() -> true);
它實際上是被invoke(Callable)
。 原因是:
() -> true
是一個形式參數為零並返回結果的 lambda 表達式。Callable
接口的函數方法call()
兼容。 請注意,接口不需要有@FunctionalInterface
注釋,它只需要有一個抽象方法。 如果要改為調用invoke(Runnable)
,則需要創建一個與采用零參數且不返回結果的函數式方法兼容的 lambda(即符合run()
的簽名)。 像這樣的東西:
invoke(() -> System.out.println("foo"));
運行時只打印foo
。
一個 lambda 表達式提供了一個函數式接口的實現。 這就是您的代碼片段所做的。
您對invoke
傳遞了一個不帶參數的 lambda 表達式,該表達式返回一個值(在您的情況下為boolean
)。 因此它匹配Object invoke(Callable c)
,而不是void invoke(Runnable r)
(因為Callable
的call
方法有一個返回值,而Runnable
的run
方法不返回任何東西)。
invoke(() -> {System.out.println("something");});
將調用void invoke(Runnable r)
,因為在這種情況下 lambda 表達式沒有返回類型。
只有當我們實現一個接口並覆蓋它的方法時
這或多或少就是你在這里所做的。 不是方法s ,而是一種方法: call()
。 這個() -> true
部分是你對Callable#call()
。
換句話說,這一行:
String s = (String) invoke(() -> true);
將完全等同於這個:
String s = (String) invoke(new Callable() {
@Override
public Object call() throws Exception {
return true;
}
});
LambdaParameters -> LambdaBody
用於定義 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)的實例。
看看下面的例子。
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.