近期由于新冠疫情的原因,不能出去游玩,只能在家呆着。于是闲来无事,开始阅读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新特性之(二)--方法引用

JDK1.8新特性之(一)--Lambda表达式的更多相关文章

  1. Java8新特性之一:Lambda表达式

    Java8是自java5之后最重大的一次更新,它给JAVA语言带来了很多新的特性(包括编译器.类库.工具类.JVM等),其中最重要的升级是它给我们带来了Lambda表达式和Stream API. 1. ...

  2. Java8新特性之forEach+Lambda 表达式遍历Map和List

    这是Java8系列的第二篇,今天来说一下Java8中forEach的简单使用.我们使用对比的方式来看应该会看得更加清楚,更能理解: 一.遍历Map ============Java8之前的方式==== ...

  3. C++11中新特性之:lambda 表达式

    首先摆出Lambda表达式语法 lambda-expression: lambda-introducer lambda-declaratoropt compound-statementlambda-i ...

  4. java8新特性:内存和lambda表达式

    1.内存变化 取消了永久区和方法区,取而代之的是MetaSpace元空间,即直接使用物理内存,即电脑内存8G则直接使用8g内存,而不是分配内存.因为内存改变,所以调整性能对应的调整参数也随之改变. 2 ...

  5. java8新特性1:lambda表达式和函数式接口

    1.lambda的介绍: 1.1.为什么java语言需要引入lambda表达式? java语言诞生于1995年,历史时间已经相对较长了.在其后的各种新型编程语言中,都有着lambda表达式的内容,并且 ...

  6. Java8新特性(1):Lambda表达式

    Lambda表达式可以理解为一种匿名函数:没有名称,但有参数列表.函数主体.返回类型.它是行为参数化的一种实现,行为参数化是指将不同的行为作为参数传递给方法,方法的所具备的能力取决于它接收的行为参数. ...

  7. Java8新特性探索之Lambda表达式

    为什么引入Lambda表达式? Lambda 表达式产生函数,而不是类. 在 JVM(Java Virtual Machine,Java 虚拟机)上,一切都是一个类,因此在幕后执行各种操作使 lamb ...

  8. JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用

    jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default   Lambda表达式     L ...

  9. JDK1.8 新特性

    jdk1.8新特性知识点: Lambda表达式 函数式接口 *方法引用和构造器调用 Stream API 接口中的默认方法和静态方法 新时间日期API https://blog.csdn.net/qq ...

随机推荐

  1. jieba分词-强大的Python 中文分词库

    1. jieba的江湖地位 NLP(自然语言)领域现在可谓是群雄纷争,各种开源组件层出不穷,其中一支不可忽视的力量便是jieba分词,号称要做最好的 Python 中文分词组件. 很多人学习pytho ...

  2. 【学习中】Unity<中级篇> Schedule

    章节 内容 签到 Unity3D 实战技术第二版视频教程(中级篇) 1.游戏引擎发展史 2.Unity发展史 3.3D图形学与必要组件 5月19日 4.核心类_GameObject类 5月19日 5. ...

  3. Codeforece E. Anton and Permutation

    主席树算贡献l,r中交换位置,算出>=rank(h) 和 <=rank(h) a[l],a[r] 先不统计 a[l]比a[r]大的话交换后ans-1,a[l]比a[r]小的话交换后ans- ...

  4. python3笔记-列表

    列表去重的两种方式: # 创建列表放数据 a =[1,2,1,4,2] b=[1,3,4,3,1,3] d=[] for i in a: if i not in d: d.append(i) prin ...

  5. 开源基于lua gc管理c++对象的cocos2dx lua绑定方案

    cocos2dx目前lua对应的c++对象的生命周期管理,是基于c++析构函数的,也就是生命周期可能存在不一致,比如c++对象已经释放,而lua对象还存在,如果这时候再使用,会有宕机的风险,为此我开发 ...

  6. 你不得不知的Java基础知识

    本篇博客主要记录Java中面向对象的概念和Java语法的基础知识. 面向对象 什么是面向对象 面向对象是一种优秀的软件设计思想,是相对于面向过程.面向切面等设计思想的一种软件设计理念.它的核心思想是运 ...

  7. JQuery生成图片列表

    <!DOCTYPE html> <html> <head> <title>生成图片列表</title> <style type=&qu ...

  8. DSRC和USRP的购买调研

    (转移自旧博客) 11.29 2019 实验室采购,所以进行了一定程度的调研. 主要包括两个Part,分别是DSRC和USRP的简单总结,购买建议和详细资料. Part.1 DSRC调研总结 1.1 ...

  9. uniapp接入友盟统计

    话不多说,上图 如果找不到上图,那就下图: 然后就隔天去平台看数据吧 ^_^

  10. Apache Nginx Tomcat

    Tomcat Tomcat:动态解析容器 处理动态请求,是编译JSP/Servlet的容器 区别: 严格意义上来说 Apache和nginx应该叫做HTTP Server tomcat是一个Appli ...