JDK1.8新特性之(一)--Lambda表達式


       近期由於新冠疫情的原因,不能出去游玩,只能在家呆着。於是閑來無事,開始閱讀JDK1.8的源代碼。在開始之前也查詢了以下JDK1.8的新特性,有針對性的開始了這段旅程。

只看不操作,也是不能心領神會的。而且好腦子不如爛筆頭。在這里記載一下自己的學習成果。也算是做一下總結吧。

在正文開始之前先看看JDK1.8都有哪些新特性?

1.Lambda表達式

2.方法引用

3.函數式接口

4.默認方法

5.Stream

6.Optional類

7.Nashorm javascript引擎

8.新的日期時間API

9.Base64

這篇文章先來學習第一個特性--Lambda表達式。

話不多說,下面正式開始學習!

(一)首先介紹以下Lambda表達式是啥?

Lambda表達式也稱作閉包,允許把函數作為一個方法的參數,使用Lamba表達式可以使代碼變得更加簡潔。

(二)Lambda表達式的語法

(參數) -> {代碼塊}

(三)Lambda表達式的特性

1.可選類型聲明:參數的類型可以省,編譯器自動識別數據類型。
2.可選的參數圓括號:參數只有一個時候可以省略圓括號。
3.可選的代碼塊大括號:代碼塊只有一行的時候可以省略大括號。
4.可選的返回關鍵字:代碼塊只有一行且有返回結果,那么return也可以省略。
(四)實例

書寫測試類之前先定義以下兩個內部接口,供測試時使用

MathOperation是用於計算數值的接口。

Service是用於提示某些信息的接口。

1 //定義數學操作接口
2 interface MathOperation{ 3  Integer operation(Integer i1,Integer i2); 4 } 5 
6 //定義服務接口
7 interface Service{ 8     void sayHello(String message); 9 }

為了便於理解Lambda表達式和更加突出其優點,先用普通的書寫方式實現MathOpertation的加法,減法,乘法,除法。

 1 //加法
 2 MathOperation mathOperation1 = new MathOperation() {  3  @Override  4     public Integer operation(Integer i1, Integer i2) {  5         return i1 + i2;  6  }  7 };  8 System.out.println("1+2=" + mathOperation1.operation(1,2));  9 
10 //減法
11 MathOperation mathOperation2 = new MathOperation() { 12  @Override 13     public Integer operation(Integer i1, Integer i2) { 14         return i1 - i2; 15  } 16 }; 17 System.out.println("4-3=" + mathOperation2.operation(4,3)); 18 
19 //乘法
20 MathOperation mathOperation3 = new MathOperation() { 21  @Override 22     public Integer operation(Integer i1, Integer i2) { 23         return i1 * i2; 24  } 25 }; 26 System.out.println("5*6=" + mathOperation3.operation(5,6)); 27 
28 //除法
29 MathOperation mathOperation4 = new MathOperation() { 30  @Override 31     public Integer operation(Integer i1, Integer i2) { 32         return i1 / i2; 33  } 34 }; 35 System.out.println("8/2=" + mathOperation4.operation(8,2));

結果:

1+2=3
4-3=1
5*6=30
8/2=4

最先用Lambda表達式的標准實現方式(沒有任何省略簡寫)

 1 //加法
 2 MathOperation mathOperation9 = (Integer i1,Integer i2) -> {return i1 + i2;};  3 System.out.println("1+2= " + mathOperation9.operation(1,2));  4 
 5 //減法
 6 MathOperation mathOperation10 = (Integer i1,Integer i2) -> {return i1 - i2;};  7 System.out.println("4-3= " + mathOperation10.operation(4,3));  8 
 9 //乘法
10 MathOperation mathOperation11 = (Integer i1,Integer i2) -> {return i1 * i2;}; 11 System.out.println("5*6= " + mathOperation11.operation(5,6)); 12 
13 //除法
14 MathOperation mathOperation12 = (Integer i1,Integer i2) -> {return i1 / i2;}; 15 System.out.println("8/2= " + mathOperation12.operation(8,2));

結果:

1+2= 3
4-3= 1
5*6= 30
8/2= 4

對比上面以前的寫法和Lambda表達式的寫法,不難看出,從代碼量上減少了很多,變得更加簡潔。

從深層次的比較就會發現,Lambda表達式替代的就是

new MathOperation() {

    XXXXX//此處省略

};

部分由此得出結論:Lambda表達式的實質就是匿名內部類

接下來逐一用實例來說明Lambda的特性。

1.可選類型聲明:參數的類型可以省,編譯器自動識別數據類型。

 1 //加法
 2 MathOperation mathOperation9 = (i1,i2) -> {return i1 + i2;};  3 System.out.println("1+2= " + mathOperation9.operation(1,2));  4 
 5 //減法
 6 MathOperation mathOperation10 = (i1,i2) -> {return i1 - i2;};  7 System.out.println("4-3= " + mathOperation10.operation(4,3));  8 
 9 //乘法
10 MathOperation mathOperation11 = (i1,i2) -> {return i1 * i2;}; 11 System.out.println("5*6= " + mathOperation11.operation(5,6)); 12 
13 //除法
14 MathOperation mathOperation12 = (i1,i2) -> {return i1 / i2;}; 15 System.out.println("8/2= " + mathOperation12.operation(8,2));

結果:

1+2= 3
4-3= 1
5*6= 30
8/2= 4

2.可選的參數圓括號:參數只有一個時候可以省略圓括號。

1 //省略版表達式
2 Service service2 = message -> System.out.println("Hello," + message); 3 service2.sayHello("Lambda表達式!");

結果:

Hello,Lambda表達式!

3.可選的代碼塊大括號:代碼塊只有一行的時候可以省略大括號。

4.可選的返回關鍵字:代碼塊只有一行且有返回結果,那么return也可以省略。

 1 //加法
 2 MathOperation mathOperation13 = (Integer i1,Integer i2) -> i1 + i2;  3 System.out.println("1+2= " + mathOperation13.operation(1,2));  4 
 5 //減法
 6 MathOperation mathOperation14 = (Integer i1,Integer i2) -> i1 - i2;  7 System.out.println("4-3= " + mathOperation14.operation(4,3));  8 
 9 //乘法
10 MathOperation mathOperation15 = (Integer i1,Integer i2) -> i1 * i2; 11 System.out.println("5*6= " + mathOperation15.operation(5,6)); 12 
13 //除法
14 MathOperation mathOperation16 = (Integer i1,Integer i2) -> i1 / i2; 15 System.out.println("8/2= " + mathOperation16.operation(8,2));

結果:

1+2= 3
4-3= 1
5*6= 30
8/2= 4

Lambda表達式除了上面幾個特性之外還有幾個地方需要注意。

1)Lambda表達式內部可以訪問外部的局部變量。

2)Lambda表達式被使用的外部局部變量默認是final類型的,不能修改其值,否則報錯。

3)Lambda表達式的內部使用的變量名稱不能和外部使用的局部變量名稱一樣,否則會報錯。

1)實例如下

 1 /**
 2  * Lambda表達式內部可以訪問外層的局部變量  3  */
 4 //顯性final
 5 final String pre_Str1 = "Test1";  6 Service service3 = message -> System.out.println("顯性final:" + pre_Str1 + message);  7 service3.sayHello(" Jay");

執行結果:

顯性final:Test1 Jay

2)實例如下

     當對變量pre_Str2進行修改后,會出現編譯錯誤:local variables referenced from a lambda expression must be final or effectively final。由此說明,引用的變量必須是final類型的。

 1 //隱形final
 2 String pre_Str2 = "Test2";  3 Service service4 = message -> System.out.println("隱形final:" + pre_Str2 + message);  4 service4.sayHello(" Jay");  5 
 6 /**
 7  * Lambda表達中被使用的外部變量默認是final類型的。也就是說不能修改變量的值。  8  * 如果試圖修改變量的值則會報如下錯誤  9  * Error:local variables referenced from a lambda expression must be final or effectively final 10  */
11 //pre_Str2 ="aaaaa";

3)實例如下

  當在Lambda表達式中使用外部局部變量pre_Str3的時候,編譯器報錯:ariable pre_Str3 is already defined in method main(java.lang.String[])。由此說明變量的名稱不能相同。

1 /**
2  * Lambda表達式的局部變量不可以和外部變量名稱相同。 3  * 如果Lambda表達式的局部變量和外部變量名稱相同則報錯。錯誤信息如下。 4  * Error:variable pre_Str3 is already defined in method main(java.lang.String[]) 5  */
6 // String pre_Str3 = "Test3"; 7 // Service service5 = pre_Str3 -> System.out.println("變量名測試:" + pre_Str2 + pre_Str3); 8 // service5.sayHello(" Jay");

以上就是我對Lambda表達式的理解。如果有理解不對或者記述錯誤的地方歡迎指正,互相學習,提升自己。

 

下面是我測試的完整類和完整結果。有需要的可以參考。

 1 package com.dream.test.JDK8speciality;  2 
 3 import java.util.*;  4 
 5 /**
 6  * @author 匠人碼農  7  * @date 2020/05/04 21:31  8  * 概要:  9  * Lambda表達式理解  10  * Lambda格式  11  * (參數) -> {代碼塊}  12  * 注:  13  * 1.可選類型聲明:參數的類型可以省,編譯器自動識別數據類型。  14  * 2.可選的參數圓括號:參數只有一個時候可以省略圓括號。  15  * 3.可選的代碼塊大括號:代碼塊只有一行的時候可以省略大括號。  16  * 4.可選的返回關鍵字:代碼塊只有一行且有返回結果,那么return也可以省略。  17  * 5.Lambda表達式的局部局部變量默認是final類型的。  18  * 6.Lambda表達式內部可以引用Lambda表達式外部的局部變量,而且必須是final類型的。  19  * 7.Lambda表達式內部的局部變量名稱不可以和Lambda表達式外部的局部變量的名稱一樣。  20  */
 21 
 22 public class LambdaTest {  23     public static void main(String[] args) {  24 
 25         //沒有Lambda表達式之前實現MathOperation的operation方法
 26         System.out.println("***************************************************");  27         System.out.println("* 沒有Lambda表達式之前實現MathOperation的operation方法");  28         System.out.println("***************************************************");  29 
 30         //加法
 31         MathOperation mathOperation1 = new MathOperation() {  32  @Override  33             public Integer operation(Integer i1, Integer i2) {  34                 return i1 + i2;  35  }  36  };  37         System.out.println("1+2=" + mathOperation1.operation(1,2));  38 
 39         //減法
 40         MathOperation mathOperation2 = new MathOperation() {  41  @Override  42             public Integer operation(Integer i1, Integer i2) {  43                 return i1 - i2;  44  }  45  };  46         System.out.println("4-3=" + mathOperation2.operation(4,3));  47 
 48         //乘法
 49         MathOperation mathOperation3 = new MathOperation() {  50  @Override  51             public Integer operation(Integer i1, Integer i2) {  52                 return i1 * i2;  53  }  54  };  55         System.out.println("5*6=" + mathOperation3.operation(5,6));  56 
 57         //除法
 58         MathOperation mathOperation4 = new MathOperation() {  59  @Override  60             public Integer operation(Integer i1, Integer i2) {  61                 return i1 / i2;  62  }  63  };  64         System.out.println("8/2=" + mathOperation4.operation(8,2));  65         //Lambda表達式
 66         System.out.println("***************************************************");  67         System.out.println("* Lambda表達式寫法實現MathOperation的operation方法");  68         System.out.println("***************************************************");  69 
 70         // 標准的Lambda表達式
 71         System.out.println("*****標准的Lambda表達式書寫方式*****");  72         //加法
 73         MathOperation mathOperation5 = (Integer i1,Integer i2) -> {return i1 + i2;};  74         System.out.println("1+2= " + mathOperation5.operation(1,2));  75 
 76         //減法
 77         MathOperation mathOperation6 = (Integer i1,Integer i2) -> {return i1 - i2;};  78         System.out.println("4-3= " + mathOperation6.operation(4,3));  79 
 80         //乘法
 81         MathOperation mathOperation7 = (Integer i1,Integer i2) -> {return i1 * i2;};  82         System.out.println("5*6= " + mathOperation7.operation(5,6));  83 
 84         //除法
 85         MathOperation mathOperation8 = (Integer i1,Integer i2) -> {return i1 / i2;};  86         System.out.println("8/2= " + mathOperation8.operation(8,2));  87 
 88         // 省略參數類型
 89         System.out.println("*****省略參數類型*****");  90         //加法
 91         MathOperation mathOperation9 = (i1,i2) -> {return i1 + i2;};  92         System.out.println("1+2= " + mathOperation9.operation(1,2));  93 
 94         //減法
 95         MathOperation mathOperation10 = (i1,i2) -> {return i1 - i2;};  96         System.out.println("4-3= " + mathOperation10.operation(4,3));  97 
 98         //乘法
 99         MathOperation mathOperation11 = (i1,i2) -> {return i1 * i2;}; 100         System.out.println("5*6= " + mathOperation11.operation(5,6)); 101 
102         //除法
103         MathOperation mathOperation12 = (i1,i2) -> {return i1 / i2;}; 104         System.out.println("8/2= " + mathOperation12.operation(8,2)); 105 
106         // 省略大括號省略return
107         System.out.println("*****省略大括號和return*****"); 108         //加法
109         MathOperation mathOperation13 = (Integer i1,Integer i2) -> i1 + i2; 110         System.out.println("1+2= " + mathOperation13.operation(1,2)); 111 
112         //減法
113         MathOperation mathOperation14 = (Integer i1,Integer i2) -> i1 - i2; 114         System.out.println("4-3= " + mathOperation14.operation(4,3)); 115 
116         //乘法
117         MathOperation mathOperation15 = (Integer i1,Integer i2) -> i1 * i2; 118         System.out.println("5*6= " + mathOperation15.operation(5,6)); 119 
120         //除法
121         MathOperation mathOperation16 = (Integer i1,Integer i2) -> i1 / i2; 122         System.out.println("8/2= " + mathOperation16.operation(8,2)); 123 
124         //沒有Lambda表達式之前的寫法
125         Service service0 = new Service() { 126  @Override 127             public void sayHello(String message) { 128                 System.out.println("hello: " + message); 129  } 130  }; 131         service0.sayHello("沒有Lambda表達式之前的寫法!!!"); 132 
133         //完整版表達式
134         Service service1 = (message) -> { 135             System.out.println("this is my " + message); 136  }; 137         service1.sayHello("Lambda表達式測試!"); 138 
139         //省略版表達式
140         Service service2 = message -> System.out.println("Hello," + message); 141         service2.sayHello("Lambda表達式!"); 142 
143         /**
144  * Lambda表達式內部可以訪問外層的局部變量 145          */
146         //顯性final
147         final String pre_Str1 = "Test1"; 148         Service service3 = message -> System.out.println("顯性final:" + pre_Str1 + message); 149         service3.sayHello(" Jay"); 150 
151         //隱形final
152         String pre_Str2 = "Test2"; 153         Service service4 = message -> System.out.println("隱形final:" + pre_Str2 + message); 154         service4.sayHello(" Jay"); 155 
156         /**
157  * Lambda表達中被使用的外部變量默認是final類型的。也就是說不能修改變量的值。 158  * 如果試圖修改變量的值則會報如下錯誤 159  * Error:local variables referenced from a lambda expression must be final or effectively final 160          */
161         //pre_Str2 ="aaaaa";
162 
163         /**
164  * Lambda表達式的局部變量不可以和外部變量名稱相同。 165  * 如果Lambda表達式的局部變量和外部變量名稱相同則報錯。錯誤信息如下。 166  * Error:variable pre_Str3 is already defined in method main(java.lang.String[]) 167          */
168         //String pre_Str3 = "Test3"; 169         //Service service5 = pre_Str3 -> System.out.println("變量名測試:" + pre_Str2 + pre_Str3); 170         //service5.sayHello(" Jay");
171 
172  } 173 
174     //定義數學操作接口
175     interface MathOperation{ 176  Integer operation(Integer i1,Integer i2); 177  } 178 
179     //定義服務接口
180     interface Service{ 181         void sayHello(String message); 182  } 183 
184 }
測試類

結果

 

 下一篇文章

JDK1.8新特性之(二)--方法引用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM