JDK1.8新特性之(一)--Lambda表达式
近期由于新冠疫情的原因,不能出去游玩,只能在家呆着。于是闲来无事,开始阅读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 }
结果
下一篇文章