JDK8新特性01-Lambda表达式
一、问题引出
1.为什么使用Lambda表达式
public static void main(String[] args) {//开启一个新线程new Thread(new Runnable() {@Overridepublic void run() {System.out.println("新线程执行的代码:" + Thread.currentThread().getName());}}).start();
}
2.代码分析
1.Thread类需要一个Runable接口作为参数,其中的抽象方法Run()方法是用来指定线程任务的核心
2.为了指定Run方法体,不得不需要Runable的实现类
3.为了省去定义一个Runable的实现类,不得不使用匿名内部类
4.必须覆盖重写run方法,所有的方法名称,方法参数,方法返回值不得不重写一遍,而且不能出错
5.然而实际上我们只在乎方法体的实现
二、Lambda表达式初体验
public static void main(String[] args) {new Thread(() -> {System.out.println("Lambda线程:" + Thread.currentThread().getName());}).start();
}
Lambda表达式是一个匿名函数,可以理解为一段可以传递的代码。
Lambda表达式的优点:简化了匿名内部类的使用,语法更加简单。
在编程中,lambda 表达式(或者函数)只是一个匿名函数, 即一个没有名称也没有标识符的函数。它们都被写在你需要使用的地方,通常作为其他函数的参数。
Lambda表达式的基本语法:
either
(parameters) -> expression
or
(parameters) -> { statements; }
or
() -> expression
一个典型的 lambda 表达式如下所示:
(x, y) -> x + y //这个函数接受两个参数并返回它们的和。
请注意根据 x 和 y 的类型,方法可能会在多个地方使用。参数可以匹配到 int 类型整数或者字符串类型。 根据上下文,它将两个整数相加或者两个字符串拼接。
三、编写 Lambda 表达式的规则
- lambda表达式可以有零个、一个或多个参数
- 可以显式声明参数的类型,也可以从上下文推断参数的类型
- 多个参数必须包含在括号中,并用逗号分隔,空括号用于表示零个参数
- 当只有一个参数时,如果推断它的类型,可以不使用括号。如 a -> return a * a
- lambda表达式的函数体可以包含零个,一个或多个语句。
- 如果lambda表达式的函数体只有一行,则可以不用大括号,匿名函数的返回类型与函数体表达式的返回类型相同。当函数体中大于一行代码则需要用大括号包含。
无参demo
public interface UserService {void goShow();
}
/**
*
*博主公众号:程序员飞扬
*欢迎围观,免费获取资料
*/
public class Demo03Lambda {public static void main(String[] args) {
//传统写法goShow(new UserService() {@Overridepublic void goShow() {System.out.println("show方法执行了。。。");}});System.out.println("-------------------华丽的分割线-------------------------");
//lambda写法goShow(() -> System.out.println("lambda show方法执行了"));}public static void goShow(UserService userService){userService.goShow();}
}
有参demo
public class Person {private String name;private Integer age;public Person() {}public Person(String name, Integer age) {this.name = name;this.age = age;}public void setName(String name) {this.name = name;}public void setAge(Integer age) {this.age = age;}public String getName() {return name;}public Integer getAge() {return age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}public class Demo04Lambda {public static void main(String[] args) {List<Person> list = new ArrayList<>();list.add(new Person("刘德华",28));list.add(new Person("郭富城",22));list.add(new Person("古天乐",36));//传统写法Collections.sort(list, new Comparator<Person>() {@Overridepublic int compare(Person o1, Person o2) {return o1.getAge()-o2.getAge();}});for (Person person:list){System.out.println(person.toString());}System.out.println("--------------我是分割线------------------");//lambda写法Collections.sort(list,(Person o1,Person o2) -> {return o1.getAge()-o2.getAge();});for (Person person:list){System.out.println(person.toString());}}
}
四、Lambda表达式原理
1.首先看匿名内部类的本质是在编译时生成一个****$1.class文件
/**
*
*博主公众号:程序员飞扬
*欢迎围观,免费获取资料
*/
public class Demo01Lambda {public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {System.out.println("新线程执行的代码:" + Thread.currentThread().getName());}}).start();}
}
编译后:
反编译匿名内部类:
public class Demo01Lambda
{public static void main(String[] args){new Thread(new Runnable(){public void run(){System.out.println("新线程执行的代码:" + Thread.currentThread().getName());}}).start();System.out.println("主线程:" + Thread.currentThread().getName());}
}final class Demo01Lambda$1implements Runnable
{public void run(){System.out.println("新线程执行的代码:" + Thread.currentThread().getName());}
}
2.lambda表达式原理
demo:
public class Demo03Lambda {public static void main(String[] args) {goShow(() -> System.out.println("lambda show方法执行了"));}public static void goShow(UserService userService){userService.goShow();}
}
利用反编译工具查看.class发现无法反编译
再利用jdk自带的反汇编工具javap查看:
.class文件目录下执行命令:
javap -c -p ***.class
-c 反汇编
-p 显示所有类和方法
D:\software\ideaSpace\JDK8-Study\target\classes\com\jdk\lambda>javap -c -p Demo03Lambda.classCompiled from "Demo03Lambda.java"public class com.jdk.lambda.Demo03Lambda {public com.jdk.lambda.Demo03Lambda();Code:0: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnpublic static void main(java.lang.String[]);Code:0: invokedynamic #2, 0 // InvokeDynamic #0:goShow:()Lcom/jdk/lambda/UserService;5: invokestatic #3 // Method goShow:(Lcom/jdk/lambda/UserService;)V8: returnpublic static void goShow(com.jdk.lambda.UserService);Code:0: aload_01: invokeinterface #4, 1 // InterfaceMethod com/jdk/lambda/UserService.goShow:()V6: returnprivate static void lambda$main$1();Code:0: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc #6 // String lambda show方法执行了5: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: return}
在反编译源码中看到,有一个静态方法lambda$main$1();然后通过debug方式可以查看到:
上面效果可以理解如下:
public class Demo03Lambda {public static void main(String[] args) {lambda$main$1();}private static void lambda$main$1(){System.out.println("lambda show方法执行了");}
}
为了更加直观的理解,我们可以在运行的时候添加 -Djdk.internal.lambda.dumpProxyClasses ,加上这个参数会将内部class码输出到文件中,可以在通过反编译工具查看.class文件
java -Djdk.internal.lambda.dumpProxyClasses 要运行的包名.方法名//例如 java -Djdk.internal.lambda.dumpProxyClasses com.jdk.lambda.Demo03Lambda
小结:
匿名内部类在编译时会产生一个class文件
Lambda表达式在程序运行时会形成一个类
1.在类中新增了一个方法,这个方法的方法体就是Lambda表达式中的代码
2.还会形成你个匿名内部类,实现接口,重写抽象方法
3.在接口中重写方法会调用新生成的方法
五、Lambda表达式省略写法
在lambda表达式标准写法基础上,可以使用省略写法规则:
1.小括号内的参数类型可以省略
2.如果小括号内有且仅有一个参数,小括号可以省略
3.如果大括号内有且仅有一条语句,可以同时省略大括号,return语句和分号。
demo:
public interface StudentService {void show(String name,Integer age);
}public interface OrderService {Integer show(String name);
}public class Demo05Lambda {public static void main(String[] args) {//多参数,标准写法goStudent((String name,Integer age) -> {System.out.println("goStudent1:" + name+age+" 666...");});//多参数,省略参数类型写法goStudent((name,age) -> {System.out.println("goStudent2:" + name+age+" 666...");});//多参数,省略参数类型和大括号写法goStudent((name,age) -> System.out.println("goStudent3:" + name+age+" 666..."));//单参数标准写法goOrder((String name) -> {System.out.println("goOrder1:" + name);return 666;});//单参数省略参数类型写法goOrder((name) -> {System.out.println("goOrder2:" + name);return 666;});//单参数省略参数类型和小括号写法goOrder(name -> {System.out.println("goOrder3:" + name);return 666;});//单参数,大括号只有仅有一句语句,省略参数类型,小括号,大括号,return和分号写法goOrder(name -> 666);}public static void goStudent(StudentService studentService){studentService.show("张三",22);}public static void goOrder(OrderService orderService){orderService.show("李四");}
}
六、Lambda表达式总结
Lambda表达式语法简洁,但并不是可以随便使用,有几个条件要注意:
1.方法的参数或局部变量类型必须为接口才能使用Lambda
2.接口中有且仅有一个抽象方法(@FunctionInterface注解标注的接口)
Lambda和匿名内部类的比较:
1.所需类型不一样
1)匿名内部类的类型可以是类,抽象类,接口
2)Lambda表达式需要的类型必须是接口
2.抽象方法的数量不一样
1)匿名内部类所需的接口中的抽象方法的数量是人任意的
2)Lambda表达式所需的接口中的抽象方法只能由一个
3.实现原理不一样
1)匿名内部类是在编译后生成一个.class文件
2)Lambda表达式实在程序运行时动态生成.class文件
JDK8新特性01-Lambda表达式相关推荐
- JDK8新特性之Lambda表达式
转载自 JDK8新特性之Lambda表达式 什么是Lambda表达式 Java 8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁.当开发者在编写Lambda表达式时,也会随之被编译成 ...
- JDK8新特性:Lambda表达式、Stream流、日期时间工具类
重要特性: 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值. 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号. 可选的大括号:如果主体包含了一个语句,就不需要大括号. ...
- JDK8新特性之Lambda表达式、函数式接口
JDK8特性之Lamdba.函数式接口 1. 什么是Lambda表达式 ❓ ⭐️1.1入门
- JDK8新特性之Lambda表达式和四大函数接口
在Java8中,加入了Lambda(Lambda expression),在使用它以前我们先聊聊为什么要加入Lamdba,使用它对于编程上有什么好处 一.Lamdba的作用 1.在我们需要把一些功能传 ...
- 熟悉JDK8新特性,“Lambda表达式与函数式接口”
Hello,你好呀,我是大白(●-●) 菜单 lambda表达式 函数式接口 lambda表达式 lambda表达式可以看成匿名内部类的一个简洁写法 在语法上,Lambda表达式包含三个部分: 参数列 ...
- jdk8新特性:Lambda表达式简单测试
import java.awt.event.ActionEvent; import java.awt.event.ActionListener;import javax.swing.JButton; ...
- java x=8_Java8新特性之lambda表达式
简介 Java8带来的新特性之一Lambda表达式,又称之为函数式编程,核心思想是将面向对象中的传递对象变为传递行为 语法 expression = (variable) -> anction ...
- java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合
java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合 比如,我有一张表: entity Category.java service CategoryServic ...
- 【java8新特性】——lambda表达式与函数式接口详解(一)
一.简介 java8于2014年发布,相比于java7,java8新增了非常多的特性,如lambda表达式.函数式接口.方法引用.默认方法.新工具(编译工具).Stream API.Date Time ...
- java8新特性之lambda表达式--超级详细版本
java8新特性之lambda表达式 1.什么是lambda表达式?为什么用它? 2. 为什么Java需要lambda表达式? 3. lambda表达式的语法 4.函数式接口 4.1 什么是函数式接口 ...
最新文章
- 2020年ACM团队新生第一次周赛题解
- lay和lied_lie和lay的区别和用法是什么
- SSM框架的搭建(idea)
- 使用文本挖掘实现站点个性化推荐
- PHP中文乱码的常见解决方法总结
- Java01-day01【发展史、跨平台原理、JRE和JDK、常用DOS命令、关键字、常量、数据类型、变量使用的注意事项、标识符、类型转换】
- java map 输入 查询 修改_map的查询和修改方法
- linux内核测试,Linux内核测试的生命周期
- 海龟画图 python太阳花_python 简单的绘图工具turtle使用详解
- [转]面向对象的三个基本特征
- ios 中的tintColor
- Android Studio新建项目出错如何解决
- 浅谈JavaScript代码预解析 + 示例详解
- 如何通过QQ机器人技术实现禅道bug的自动提交功能
- [深度学习] ImageAI库使用笔记
- 利用JAVA流处理-统计男员工人数;找出所有薪资大于 5000 元的女员工;找出大于平均年龄的员工
- 如何在Windows命令行(DOS界面)中调用 编译器 来编译C/C++源程序
- Mac上的远程连接工具Royal TSX,比FinalShell更值得被推荐
- 因微信网页授权调整解决方案
- 学术诚信的重要性_宋瑞:坚持学术诚信 恪守学术道德 捍卫学术尊严
热门文章
- win10两个磁盘合并成一个?win10系统怎么合并磁盘
- 1000个瓶子和10只老鼠问题浅解
- 如何在linux服务器下载文件夹,linux服务器怎么下载文件到本地
- lol国服维护可以玩别的服务器吗,LOL:除了艾欧尼亚,其他服务器都只能算是“郊区”吗?...
- [c++]一个简单的NEAT机器学习寻路实验
- “人机大战”简单复盘
- Windows 搜索
- 面向大规模流量活动的高可用架构实践
- Keras之TCN:基于keras框架利用时间卷积网络TCN算法对上海最高气温实现回归预测(把时间序列数据集转化为有监督学习数据集)案例
- 如何着手写一篇医学综述?