目錄
1 Lambda表達式簡介
1.1 Lambda表達式是什麼
JDK1.8是目前最流行的JDK版本,在這一個版本中引入了Lamda表達式。Lambda表達式可以簡化代碼,讓我們的代碼更爲優雅,而Lambda表達式之所以“優雅”,是因爲使用Lambda表達式可以對接口進行簡潔的實現,Lamdba表達式本身就是一個匿名函數。
1.2 使用Lambda表達式實現Runnable接口
在Java中,線程可以通過將實現了Runnable接口的對象作爲Thread類構造函數的參數進行創建,比如以下代碼。
public class TestThread {
public static void main(String[] args) {
Thread thread = new Thread(new MyTest());
thread.start();
}
}
class MyTest implements Runnable {
@Override
public void run() {
System.out.println("執行線程內容");
}
}
當然,也可以使用匿名函數的形式去創建一個線程,使代碼的編寫更加靈活,如以下代碼所示。
public class TestThread {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("執行線程內容");
}
});
thread.start();
}
}
在上面的代碼中,Runnable是一個接口,直接使用new去創建對象,也必須實現接口中的方法,這裏就是匿名函數。而對於匿名函數的實現我們就可以用到Lambda表達式,如以下代碼所示。
public class TestThread {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("執行線程內容");
});
thread.start();
}
}
2 Lambda表達式語法
2.1 Lambda表達式基礎語法
在上面使用創建線程簡述了Lambda表達式的用法,這裏詳細描述Lambda表達式的基礎語法。
Thread thread = new Thread(() -> {
System.out.println("執行線程內容");
});
以這一段代碼作爲參考
():表示的是參數的列表,Runnable接口當中的run()方法沒有參數,所以()裏面是沒有參數的;
->:Lambda表達式的運算符,指向方法體;
{}:用來描述方法體。
所以,這裏new Thread()中代碼段的意思就是創建了一個Runnable接口的實現類,並且實現了接口中無參的抽象方法run,方法體爲System.out.println("執行線程內容")。
爲什麼這裏並沒有出現Runnable這一個名稱程序卻知道實現的是Runnble接口,而如果這一個接口中有兩個或者多個抽象類程序會怎麼解析?對於這兩個疑問,首先可以查看Thread類的源碼,就是下面的代碼段。
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
這是Thread類單個參數的構造方法,參數就是Runnable,所以這裏使用Lambda表達式程序可以知道這裏實現的Runnbale接口。而對於一個接口中有多個抽象方法的問題,Lambda表達式有這樣的使用要求,就是在接口中有且只有一個抽象方法,如果Runnble接口中有兩個或者多個抽象方法我們是不能這麼用的。並且,打開Runnable接口的源碼我們可以發現,在interface上有一個註解@FunctionalInterface,從名稱可以看出這個註解的意思是函數式接口,也就是說這個接口裏面只能有一個方法,否則會報錯。
2.2 Lambda表達式基礎語法擴展
上面以class Thread與interface Runnable爲例介紹了抽象方法在無參、無返回值情況下的實現,介紹了Lambda表達式的基礎語法,這裏就對Lambda表達式的語法進行一個擴展介紹。
(1)以一個參數,沒有返回值的抽象方法舉例,首先聲明這樣一個接口,如以下代碼所示。
@FunctionalInterface
public interface NoReturnOneParamInterface {
void test(int num);
}
使用Lambda表示式創建這個接口的實現對象,可以這樣寫。
public class Test01 {
public static void main(String[] args) {
NoReturnOneParamInterface noReturnOneParamInterface = (int num) -> {
System.out.println(num);
};
noReturnOneParamInterface.test(100); // 結果爲在控制檯打印了100
}
}
(2)以兩個參數,沒有返回值的抽象方法舉例,接口聲明及方法實現方式如下。
@FunctionalInterface
public interface NoReturnTwoParamInterface {
void test(int a, int b);
}
public class Test01 {
public static void main(String[] args) {
NoReturnTwoParamInterface noReturnTwoParamInterface = (int a, int b) -> {
System.out.println(a + b);
};
noReturnTwoParamInterface.test(100, 1000); // 結果爲在控制檯打印了1100
}
}
(3)以任意參數,有返回值的抽象方法舉例,接口聲明及方法實現方式如下。
@FunctionalInterface
public interface HasReturnTwoParamInterface {
int test(int a, int b);
}
public class Test01 {
public static void main(String[] args) {
HasReturnTwoParamInterface hasReturnTwoParamInterface = (int a, int b) -> {
System.out.println(a + b);
return a + b;
};
int test = hasReturnTwoParamInterface.test(100, 1000); // 此時int變量的值爲1100
System.out.println(test);
}
}
2.3 Lambda表達式簡寫
Lambda表達式在一定程度上精簡了代碼,並且在上面所提到的語法基礎上還有一些簡寫語法,有代碼潔癖的人士也許會很喜歡。
(1)參數類型簡寫
由於方法參數類型在接口定義時早已聲明,在編譯時JVM是可以知道方法參數類型的,所以在使用Lambda表達式去寫有參的匿名函數時可以省略調參數類型。當然,如果要省去參數類型必須該方法的所有參數的類型都不寫,否則通不過編譯。示例爲如下代碼。
public class Test01 {
public static void main(String[] args) {
HasReturnTwoParamInterface hasReturnTwoParamInterface = (a, b) -> {
System.out.println(a + b);
return a + b;
};
int test = hasReturnTwoParamInterface.test(100, 1000); // 此時int變量的值爲1100
System.out.println(test);
}
}
(2)方法體只有一行時可以省去大括號
這裏意思就是說當抽象方法的實現只有一個分號時可以省去包圍方法體的大括號,如下代碼所示。
public class Test01 {
public static void main(String[] args) {
NoReturnOneParamInterface noReturnOneParamInterface = (a) -> System.out.println("hello world");
noReturnOneParamInterface.test(1000);
}
}
需要注意的是,如果是在省去了大括號並且唯一的一條語句是一個return,則必須省去return關鍵字,當然省去return關鍵字還是會返回的。
(3)參數只有一個時可以省去包圍參數的小括號
沒錯,這樣也是可以運行的。
public class Test01 {
public static void main(String[] args) {
NoReturnOneParamInterface noReturnOneParamInterface = a -> System.out.println("hello world");
noReturnOneParamInterface.test(1000);
}
}