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