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

任何人都可以幫助我理解這一點嗎? 我的印象是,只有在實現接口並覆蓋其方法(用 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) (因為Callablecall方法有一個返回值,而Runnablerun方法不返回任何東西)。

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 : 只能用於執行后台任務(這里編譯器自己計算)
  • 表達式:返回某種值

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 中還有更多很棒的東西......

看看下面的例子。

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