天天看點

Lambda 表達式入門,看這篇就夠了

說出來怕你們不相信,剛接到物業通知,疫情防控更新了,車輛隻能出不能進,每戶家庭每天可指派 1 名成員上街采購生活用品。這不是謠言,截個圖自證清白,出自洛陽市湖北路街道處。

Lambda 表達式入門,看這篇就夠了
看來事态嚴峻,這樣看似好心,但不一定辦好事,去逾時搶購的人會更多。不管了,隻能窩在家做持久戰了。趁這段時間,多分享一些原創文章給你們——有眼福了呀,多儲備點知識,疫情結束後肯定能派上大用場。今天分享的主題是《Lambda 表達式》,這也是之前一些讀者留言強烈要求我寫一寫的,不好意思,讓你們久等了,現在來滿足你們,為時不晚吧?
Lambda 表達式入門,看這篇就夠了

01、初識 Lambda

Lambda 表達式描述了一個代碼塊(或者叫匿名方法),可以将其作為參數傳遞給構造方法或者普通方法以便後續執行。考慮下面這段代碼:

() -> System.out.println("沉默王二")
           

來從左到右解釋一下,

()

為 Lambda 表達式的參數清單(本例中沒有參數),

->

辨別這串代碼為 Lambda 表達式(也就是說,看到

->

就知道這是 Lambda),

System.out.println("沉默王二")

為要執行的代碼,即将“沉默王二”列印到标準輸出流。

有點 Java 基礎的同學應該不會對 Runnable 接口感到陌生,這是多線程的一個基礎接口,它的定義如下:

@FunctionalInterface
public interface Runnable
{
   public abstract void run();
}
           

Runnable 接口非常簡單,僅有一個抽象方法

run()

;細心的同學會發現一個陌生的注解

@FunctionalInterface

,這個注解是什麼意思呢?

我看了它的源碼,裡面有這樣一段注釋:

Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references.

大緻的意思就是說,通過

@FunctionalInterface

标記的接口可以通過 Lambda 表達式建立執行個體。具體怎麼表現呢?

原來我們建立一個線程并啟動它是這樣的:

public class LamadaTest {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("沉默王二");
            }
        }).start();
    }
}
           

通過 Lambda 表達式呢?隻需要下面這樣:

public class LamadaTest {
    public static void main(String[] args) {
        new Thread(() -> System.out.println("沉默王二")).start();
    }
}
           

是不是很妙!比起匿名内部類,Lambda 表達式不僅易于了解,更大大簡化了必須編寫的代碼數量。

Lambda 表達式入門,看這篇就夠了

02、Lambda 文法

每個 Lambda 表達式都遵循以下法則:

( parameter-list ) -> { expression-or-statements }
           

()

中的

parameter-list

是以逗号分隔的參數。你可以指定參數的類型,也可以不指定(編譯器會根據上下文進行推斷)。Java 11 後,還可以使用

var

關鍵字作為參數類型,有點 JavaScript 的味道。

->

相當于 Lambda 的辨別符,就好像見到聖旨就見到了皇上。

{}

expression-or-statements

為 Lambda 的主體,可以是一行語句,也可以多行。

可以通過 Lambda 表達式幹很多事情,比如說

1)為變量指派,示例如下:

Runnable r = () -> { System.out.println("沉默王二"); };
r.run();
           

2)作為 return 結果,示例如下:

static FileFilter getFilter(String ext)
{
    return (pathname) -> pathname.toString().endsWith(ext);
}
           

3)作為數組元素,示例如下:

final PathMatcher matchers[] =
{
        (path) -> path.toString().endsWith("txt"),
        (path) -> path.toString().endsWith("java")
};
           

4)作為普通方法或者構造方法的參數,示例如下:

new Thread(() -> System.out.println("沉默王二")).start();
           

需要注意 Lambda 表達式的作用域範圍。

public static void main(String[] args) {

    int limit = 10;
    Runnable r = () -> {
        int limit = 5;
        for (int i = 0; i < limit; i++)
            System.out.println(i);
    };
}
           

上面這段代碼在編譯的時候會提示錯誤:變量 limit 已經定義過了。

和匿名内部類一樣,不要在 Lambda 表達式主體内對方法内的局部變量進行修改,否則編譯也不會通過:Lambda 表達式中使用的變量必須是 final 的。

Lambda 表達式入門,看這篇就夠了

03、Lambda 和 this 關鍵字

Lambda 表達式并不會引入新的作用域,這一點和匿名内部類是不同的。也就是說,Lambda 表達式主體内使用的 this 關鍵字和其所在的類執行個體相同。

來看下面這個示例。

public class LamadaTest {
    public static void main(String[] args) {
        new LamadaTest().work();
    }

    public void work() {
        System.out.printf("this = %s%n", this);

        Runnable r = new Runnable()
        {
            @Override
            public void run()
            {
                System.out.printf("this = %s%n", this);
            }
        };
        new Thread(r).start();
        new Thread(() -> System.out.printf("this = %s%n", this)).start();
    }
}
           

Tips:

%s

代表目前位置輸出字元串,

%n

代表換行符,也可以使用

\n

代替,但

%n

是跨平台的。

work()

方法中的代碼可以分為 3 個部分:

1)單獨的 this 關鍵字

System.out.printf("this = %s%n", this);
           

其中 this 為

main()

方法中通過 new 關鍵字建立的 LamadaTest 對象——

new LamadaTest()

2)匿名内部類中的 this 關鍵字

Runnable r = new Runnable()
{
    @Override
    public void run()
    {
        System.out.printf("this = %s%n", this);
    }
};
           

work()

方法中通過 new 關鍵字建立的 Runnable 對象——

new Runnable(){...}

3)Lambda 表達式中的 this 關鍵字

其中 this 關鍵字和 1)中的相同。

我們來看一下程式的輸出結果:

this = com.cmower.java_demo.journal.LamadaTest@3feba861
this = com.cmower.java_demo.journal.LamadaTest$1@64f033cb
this = com.cmower.java_demo.journal.LamadaTest@3feba861
           

符合我們分析的預期。

Lambda 表達式入門,看這篇就夠了

04、最後

盡管 Lambda 表達式在簡化 Java 程式設計方面做了很多令人驚訝的努力,但在某些情況下,不當的使用仍然會導緻不必要的混亂,大家夥慎用。

好了,我親愛的讀者朋友們,以上就是本文的全部内容了。能在疫情期間堅持看技術文,二哥必須要伸出大拇指為你點個贊👍,疫情過後,我相信你的才華一定會展露無疑。

原創不易,如果覺得有點用的話,請不要吝啬你手中點贊的權力——因為這将是我寫作的最強動力。

Lambda 表達式入門,看這篇就夠了

微信掃描左側二維碼,關注作者的微信公衆号:「

沉默王二

背景回複“

666

”即可擷取一份 500G 的高清教學視訊,并且已經分門别類,可以按需下載下傳,速去!

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

如果覺得還有幫助的話,可以點一下右下角的【推薦】。