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新特性之(二)--方法引用

posted @ 2020-05-21 22:28  匠人码农  阅读(...)  评论(...编辑  收藏