本文已受權"後端技術精選"獨家發佈。java
「Lambda 表達式」(lambda expression)是一個匿名函數,Lambda表達式基於數學中的λ演算得名,直接對應於其中的lambda抽象(lambda abstraction),是一個匿名函數,即沒有函數名的函數。Lambda表達式能夠表示閉包(注意和數學傳統意義上的不一樣)。express
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();
複製代碼
和實現某接口的對象不一樣,咱們傳入了一段代碼塊--一個沒有名字的函數。->
將參數和表達式主體分開,左邊是參數,右邊是方法體。bash
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只能用於函數式接口),若是參數只包含一個參數,能夠省略參數的括號。ide
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+y
,Test2
對象不是表示兩個數字的和,而是表示兩個數字相加的代碼。以上的代碼中,參數類型都是由編譯器本身推斷的,一樣,咱們能夠明確的聲明參數類型:函數
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 表達式引用的本地變量必須是最終變量或實際上的最終變量ui
String name = "FantJ";
Runnable runnable = ()-> System.out.println("hello " +name);
runnable.run();
複製代碼
hello FantJ
複製代碼
上面這段代碼,Lambda能夠引用非final變量這個屬性你能夠早已瞭解,可是你更須要知道,java8只是放鬆了這一語法的限制,但實際上要求該變量仍是final。spa
能夠看到,無論name
在使用lambda
的前仍是後作改動,lambda
都會報錯:表達式引用的本地變量必須是最終變量或實際上的最終變量,簡單的,咱們能夠稱他爲既成事實上的final變量。因此,lambda也被稱爲閉包。設計
java中,全部方法都有返回類型,那lambda返回類型是什麼呢。
是接口方法的返回類型。這一點前文有體現過。這裏再詳細解釋下。
interface Test{
void oneParam(String name);
}
複製代碼
拿這個例子來說,oneParam
方法表示一種行爲:接受一個String
,返回void
。只要方法名和行爲和Lambda表達式匹配便可完成調用。
注意:若是編譯器猜不出參數和返回值的類型,則都將視爲Object
處理。