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 ...
随机推荐
- 关于Chrome浏览器自动同步的问题
Chrome浏览器是开发者最喜欢的浏览器,没有之一,那么公司办公和在家办公的话数据需要有一致性,这个时候就用到了浏览器的自动同步的功能 因为网络的问题,谷歌账户很难登录,基本需要VPN翻墙处理之后才能 ...
- 【Android】Android开发实现进度条效果,SeekBar的简单使用。音量,音乐播放进度,视频播放进度等
作者:程序员小冰,GitHub主页:https://github.com/QQ986945193 新浪微博:http://weibo.com/mcxiaobing 首先给大家看一下我们今天这个最终实现 ...
- Ignatius and the Princess IV (水题)
"OK, you are not too bad, em... But you can never pass the next test." feng5166 says. &qu ...
- 跟着尚硅谷系统学习Docker-【day02】
day02-20200714 p9.docker阿里云配置 helloword 拉取镜像-运行- 拉取镜像如果从国外网站拉取辉比较慢,所以需要配置阿里云或者网易云得镜像仓库. 首先 ...
- Oracle的timestamp字段更新实验 结论:只有逐条更新才能保证timestamp字段有差别,批量更新只会得到一致的时间,此操作无关时间精度.
有这么一张表: create table hy_testtime( id number(6,0) not null primary key, name nvarchar2(20) not null, ...
- JDK8(jdk-8u212-windows-x64) 下载 安装 及设置
JDK8 下载页面 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 19.8.2 ...
- flutter vscode 安卓打包apk文件
配置 VSCode默认是没有使用密钥签名的,往往我们在正式项目中是需要签名的.那就创建好了...所以需要自己创建并使用密钥签名 步骤一 创建密钥库 执行以下命令: keytool -genkey -v ...
- ui自动化--鼠标操作ActionChains
需要先引入鼠标操作模块:from selenium.webdriver.common.action_chains import ActionChains 实际上ActionChains这个模块的实现的 ...
- Mybatis如何执行Select语句,你真的知道吗?
持续原创输出,点击上方蓝字关注我吧 作者:不才陈某 博客:https://chenjiabing666.github.io 前言 本篇文章是Myabtis源码分析的第三篇,前两篇分别介绍了Mybati ...
- oracle之三手工完全恢复
手工完全恢复 3.1 完全恢复:通过备份.归档日志.current log ,将database恢复到failure 前的最后一次commit状态. 3.2 完全恢复的步骤 1)restore: OS ...