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 }
测试类
结果

下一篇文章
JDK1.8新特性之(二)--方法引用
JDK1.8新特性之(一)--Lambda表达式的更多相关文章
- Java8新特性之一:Lambda表达式
Java8是自java5之后最重大的一次更新,它给JAVA语言带来了很多新的特性(包括编译器.类库.工具类.JVM等),其中最重要的升级是它给我们带来了Lambda表达式和Stream API. 1. ...
- Java8新特性之forEach+Lambda 表达式遍历Map和List
这是Java8系列的第二篇,今天来说一下Java8中forEach的简单使用.我们使用对比的方式来看应该会看得更加清楚,更能理解: 一.遍历Map ============Java8之前的方式==== ...
- C++11中新特性之:lambda 表达式
首先摆出Lambda表达式语法 lambda-expression: lambda-introducer lambda-declaratoropt compound-statementlambda-i ...
- java8新特性:内存和lambda表达式
1.内存变化 取消了永久区和方法区,取而代之的是MetaSpace元空间,即直接使用物理内存,即电脑内存8G则直接使用8g内存,而不是分配内存.因为内存改变,所以调整性能对应的调整参数也随之改变. 2 ...
- java8新特性1:lambda表达式和函数式接口
1.lambda的介绍: 1.1.为什么java语言需要引入lambda表达式? java语言诞生于1995年,历史时间已经相对较长了.在其后的各种新型编程语言中,都有着lambda表达式的内容,并且 ...
- Java8新特性(1):Lambda表达式
Lambda表达式可以理解为一种匿名函数:没有名称,但有参数列表.函数主体.返回类型.它是行为参数化的一种实现,行为参数化是指将不同的行为作为参数传递给方法,方法的所具备的能力取决于它接收的行为参数. ...
- Java8新特性探索之Lambda表达式
为什么引入Lambda表达式? Lambda 表达式产生函数,而不是类. 在 JVM(Java Virtual Machine,Java 虚拟机)上,一切都是一个类,因此在幕后执行各种操作使 lamb ...
- JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用
jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default Lambda表达式 L ...
- JDK1.8 新特性
jdk1.8新特性知识点: Lambda表达式 函数式接口 *方法引用和构造器调用 Stream API 接口中的默认方法和静态方法 新时间日期API https://blog.csdn.net/qq ...
随机推荐
- .net core 返回业务错误(不抛异常)
在开始之前你需要知道: 1.通过抛异常--全局捕获异常的方式返回业务错误信息性能是非常差的(不知道为什么的可以百度一下) 2.如何将错误信息绑定到mvc模型验证中 自定义返回内容 //返回内容接口 p ...
- 除了方文山,用TA你也能帮周杰伦写歌词了
周杰伦几乎陪伴了每个90后的青春,那如果AI写杰伦风格的歌词会写成怎样呢? 首先当然我们需要准备杰伦的歌词,这里一共收录了他的十几张专辑,近5000多行歌词. 原文档格式: 第一步数据预处理 def ...
- 英文ubuntu中的乱码,输入法问题 、mint字体发虚
英文ubuntu文本文件默认编码是utf-8,windows下是gbk,所以产生乱码问题. 1.前言 运行命令查看系统编码 $locale 结果如下: LANG=en_US.UTF-8 LANGUAG ...
- EventDispatcher
事件分发类,提供事件注册.移除.触发功能 采用delegate.dictionary实现 支持自定义事件.事件采用字符串方式标识 支持 0,1,2,3,4 等5种不同参数个数的回调函数 // 路由 ...
- java的方法详解和总结
一.什么是方法 在日常生活中,我们所说的方法就是为了解决某件事情,而采取的解决办法 java中的方法可以理解为语句的集合,用来完成解决某件事情或实现某个功能的办法 方法的优点: 程序变得更加简短而清晰 ...
- Educational Codeforces Round 68 (Rated for Div. 2)-D. 1-2-K Game
output standard output Alice and Bob play a game. There is a paper strip which is divided into n + 1 ...
- 【Oracle】SQL对某字段模糊查询,哪种方案最快?
问题:有一张表hy_test,查找其字段name中包含ufo的记录数,下面哪种方案最快? A.select count(*) from hy_test where name like '%ufo%' ...
- Mybatis源码如何阅读,教你一招!!!
前言 前一篇文章简单的介绍了Mybatis的六个重要组件,这六剑客占据了Mybatis的半壁江山,和六剑客搞了基友,那么Mybatis就是囊中之物了.对六剑客感兴趣的朋友,可以看看这篇文章:Mybat ...
- ui自动化--xpath
xpath //*代表从根节点,查找所有匹配到的元素.在filepath中输入后回车,会发现整个页面所有元素都被虚线选中 //表示跟节点 []代表要用属性定位 @表示要用什么属性 定位完成后,对应页面 ...
- 1. spring5源码 -- Spring整体脉络 IOC加载过程 Bean的生命周期
可以学习到什么? 0. spring整体脉络 1. 描述BeanFactory 2. BeanFactory和ApplicationContext的区别 3. 简述SpringIoC的加载过程 4. ...