Java 函數語言程式設計(二)Lambda表示式

微笑面對生活發表於2018-08-16

本文已授權"後端技術精選"獨家釋出。

“Lambda 表示式”(lambda expression)是一個匿名函式,Lambda表示式基於數學中的λ演算得名,直接對應於其中的lambda抽象(lambda abstraction),是一個匿名函式,即沒有函式名的函式。Lambda表示式可以表示閉包(注意和數學傳統意義上的不同)。

認識lambda

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名內部類的執行");
            }
        }).start();
    }
複製程式碼

設計匿名內部類的目的,就是為了方便程式猿將程式碼作為資料來傳遞。但是你會發現,這個物件看起來是很多餘的,所以我們不想傳入物件,只想傳入行為。

        new Thread(()->{
            System.out.println("lambda代替內部類");
        }).start();
複製程式碼

和實現某介面的物件不同,我們傳入了一段程式碼塊--一個沒有名字的函式。->將引數和表示式主體分開,左邊是引數,右邊是方法體。

Lambda的不同形式

Runnable runnable =  ()-> System.out.println("hello world");
複製程式碼

該Lambda表示式不包含引數(因為是空括號)。

    interface Test{
        void oneParam(String name);
    }

        Test test = s -> System.out.println("oneParam方法傳遞引數:"+s);
        test.oneParam("我是傳遞的值");

控制檯輸出:
oneParam方法傳遞引數:我是傳遞的值
複製程式碼

(lambda只能用於函式式介面),如果引數只包含一個引數,可以省略引數的括號。

    interface Test2{
        int add(int a,int b);
    }
    Test2 test2 = (x,y) -> x+y;
    int add = test2.add(10, 10);
    System.out.println(add);

控制檯輸出:
20
複製程式碼

可以看到,我們在使用lambda的時候建立了一個函式x+yTest2物件不是表示兩個數字的和,而是表示兩個數字相加的程式碼。以上的程式碼中,引數型別都是由編譯器自己推斷的,同樣,我們可以明確的宣告引數型別:

    interface Test3{
        long add(long a,long b);
    }

    Test3 test3 = (long x,long y) -> x+y;
    long add = test3.add(10, 10);
複製程式碼

引用值的要求

Error:(25, 64) java: 從lambda 表示式引用的本地變數必須是最終變數或實際上的最終變數

        String  name = "FantJ";
        Runnable runnable =  ()-> System.out.println("hello " +name);
        runnable.run();
複製程式碼
hello FantJ
複製程式碼

上面這段程式碼,Lambda可以引用非final變數這個屬性你可以早已瞭解,但是你更需要知道,java8只是放鬆了這一語法的限制,但實際上要求該變數還是final。

Java 函數語言程式設計(二)Lambda表示式

Java 函數語言程式設計(二)Lambda表示式

可以看到,不管name在使用lambda的前還是後做改動,lambda都會報錯:表示式引用的本地變數必須是最終變數或實際上的最終變數,簡單的,我們可以稱他為既成事實上的final變數。所以,lambda也被稱為閉包。

Lambda表示式型別

java中,所有方法都有返回型別,那lambda返回型別是什麼呢。

是介面方法的返回型別。這一點前文有體現過。這裡再詳細解釋下。

    interface Test{
        void oneParam(String name);
    }
複製程式碼

拿這個例子來講,oneParam方法表示一種行為:接受一個String,返回void。只要方法名和行為和Lambda表示式匹配即可完成呼叫。

注意:如果編譯器猜不出引數和返回值的型別,則都將視為Object處理。

相關文章