近期由於新冠疫情的原因,不能出去游玩,只能在家呆着。於是閑來無事,開始閱讀JDK1.8的源代碼。在開始之前也查詢了以下JDK1.8的新特性,有針對性的開始了這段旅程。
只看不操作,也是不能心領神會的。而且好腦子不如爛筆頭。在這里記載一下自己的學習成果。也算是做一下總結吧。
在正文開始之前先看看JDK1.8都有哪些新特性?
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新特性之(二)--方法引用

