【Java8新特性】Lambda表達式基礎語法,都在這兒了!!
寫在前面
前面積極響應讀者的需求,寫了兩篇Java新特性的文章。有小夥伴留言說:感覺Lambda表達式很強大啊!一行代碼就能夠搞定那麼多功能!我想學習下Lambda表達式的語法,可以嗎?我的回答是:沒問題!這不,Lambda表達式來了!
匿名類到Lambda表達式
我們先來看看從匿名類如何轉換到Lambda表達式呢?
這裡,我們可以使用兩個示例來說明如何從匿名內部類轉換為Lambda表達式。
- 匿名內部類到Lambda表達式
使用匿名內部類如下所示。
Runnable r = new Runnable(){
@Override
public void run(){
System.out.println("Hello Lambda");
}
}
轉化為Lambda表達式如下所示。
Runnable r = () -> System.out.println("Hello Lambda");
- 匿名內部類作為參數傳遞到Lambda表達式作為參數傳遞
使用匿名內部類作為參數如下所示。
TreeSet<Integer> ts = new TreeSet<>(new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2){
return Integer.compare(o1, o2);
}
});
使用Lambda表達式作為參數如下所示。
TreeSet<Integer> ts = new TreeSet<>(
(o1, o2) -> Integer.compare(o1, o2);
);
從直觀上看,Lambda表達式要比常規的語法簡潔的多。
Lambda表達式的語法
Lambda表達式在Java語言中引入了 「->」 操作符, 「->」 操作符被稱為Lambda表達式的操作符或者箭頭操作符,它將Lambda表達式分為兩部分:
- 左側部分指定了Lambda表達式需要的所有參數。
Lambda表達式本質上是對接口的實現,Lambda表達式的參數列表本質上對應着接口中方法的參數列表。
- 右側部分指定了Lambda體,即Lambda表達式要執行的功能。
Lambda體本質上就是接口方法具體實現的功能。
我們可以將Lambda表達式的語法總結如下。
1.語法格式一:無參,無返回值,Lambda體只有一條語句
Runnable r = () -> System.out.println("Hello Lambda");
具體示例如下所示。
@Test
public void test1(){
Runnable r = () -> System.out.println("Hello Lambda");
new Thread(r).start();
}
2.語法格式二:Lambda表達式需要一個參數,並且無返回值
Consumer<String> func = (s) -> System.out.println(s);
具體示例如下所示。
@Test
public void test2(){
Consumer<String> consumer = (x) -> System.out.println(x);
consumer.accept("Hello Lambda");
}
3.語法格式三:Lambda只需要一個參數時,參數的小括號可以省略
Consumer<String> func = s -> System.out.println(s);
具體示例如下所示。
@Test
public void test3(){
Consumer<String> consumer = x -> System.out.println(x);
consumer.accept("Hello Lambda");
}
4.語法格式四:Lambda需要兩個參數,並且有返回值
BinaryOperator<Integer> bo = (a, b) -> {
System.out.println("函數式接口");
return a + b;
};
具體示例如下所示。
@Test
public void test4(){
Comparator<Integer> comparator = (x, y) -> {
System.out.println("函數式接口");
return Integer.compare(x, y);
};
}
5.語法格式五:當Lambda體只有一條語句時,return和大括號可以省略
BinaryOperator<Integer> bo = (a, b) -> a + b;
具體示例如下所示。
@Test
public void test5(){
Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
}
6.語法格式六:Lambda表達式的參數列表的數據類型可以省略不寫,因為JVM編譯器能夠通過上下文推斷出數據類型,這就是「類型推斷」
BinaryOperator<Integer> bo = (Integer a, Integer b) -> {
return a + b;
};
等同於
BinaryOperator<Integer> bo = (a, b) -> {
return a + b;
};
上述 Lambda 表達式中的參數類型都是由編譯器推斷得出的。 Lambda 表達式中無需指定類型,程序依然可以編譯,這是因為 javac 根據程序的上下文,在後台推斷出了參數的類型。 Lambda 表達式的類型依賴於上下文環境,是由編譯器推斷出來的。這就是所謂的「類型推斷」。
函數式接口
Lambda表達式需要函數式接口的支持,所以,我們有必要來說說什麼是函數式接口。
只包含一個抽象方法的接口,稱為函數式接口。
可以通過 Lambda 表達式來創建該接口的對象。(若 Lambda表達式拋出一個受檢異常,那麼該異常需要在目標接口的抽象方法上進行聲明)。
可以在任意函數式接口上使用 @FunctionalInterface 註解,這樣做可以檢查它是否是一個函數式接口,同時 javadoc 也會包含一條聲明,說明這個接口是一個函數式接口。
我們可以自定義函數式接口,並使用Lambda表達式來實現相應的功能。
例如,使用函數式接口和Lambda表達式實現對字符串的處理功能。
首先,我們定義一個函數式接口MyFunc,如下所示。
@FunctionalInterface
public interface MyFunc <T> {
public T getValue(T t);
}
接下來,我們定義一個操作字符串的方法,其中參數為MyFunc接口實例和需要轉換的字符串。
public String handlerString(MyFunc<String> myFunc, String str){
return myFunc.getValue(str);
}
接下來,我們對自定義的函數式接口進行測試,此時我們傳遞的函數式接口的參數為Lambda表達式,並且將字符串轉化為大寫。
@Test
public void test6(){
String str = handlerString((s) -> s.toUpperCase(), "binghe");
System.out.println(str);
}
運行test6方法,得出的結果信息如下所示。
BINGHE
我們也可以截取字符串的某一部分,如下所示。
@Test
public void test7(){
String str = handlerString((s) -> s.substring(0,4), "binghe");
System.out.println(str);
}
運行test7方法,得出的結果信息如下所示。
bing
可以看到,我們可以通過handlerString(MyFunc<String> myFunc, String str)
方法結合Lambda表達式對字符串進行任意操作。
注意:作為參數傳遞 Lambda 表達式:為了將 Lambda 表達式作為參數傳遞,接收Lambda 表達式的參數類型必須是與該 Lambda 表達式兼容的函數式接口的類型 。
寫在最後
如果覺得文章對你有點幫助,請微信搜索並關注「 冰河技術 」微信公眾號,跟冰河學習Java8新特性。
最後,附上Java8新特性核心知識圖,祝大家在學習Java8新特性時少走彎路。