一、问题引出

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 表达式的规则

  1. lambda表达式可以有零个、一个或多个参数
  2. 可以显式声明参数的类型,也可以从上下文推断参数的类型
  3. 多个参数必须包含在括号中,并用逗号分隔,空括号用于表示零个参数
  4. 当只有一个参数时,如果推断它的类型,可以不使用括号。如 a -> return a * a
  5. lambda表达式的函数体可以包含零个,一个或多个语句。
  6. 如果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表达式相关推荐

  1. JDK8新特性之Lambda表达式

    转载自 JDK8新特性之Lambda表达式 什么是Lambda表达式 Java 8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁.当开发者在编写Lambda表达式时,也会随之被编译成 ...

  2. JDK8新特性:Lambda表达式、Stream流、日期时间工具类

    重要特性: 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值. 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号. 可选的大括号:如果主体包含了一个语句,就不需要大括号. ...

  3. JDK8新特性之Lambda表达式、函数式接口

    JDK8特性之Lamdba.函数式接口 1. 什么是Lambda表达式 ❓ ⭐️1.1入门

  4. JDK8新特性之Lambda表达式和四大函数接口

    在Java8中,加入了Lambda(Lambda expression),在使用它以前我们先聊聊为什么要加入Lamdba,使用它对于编程上有什么好处 一.Lamdba的作用 1.在我们需要把一些功能传 ...

  5. 熟悉JDK8新特性,“Lambda表达式与函数式接口”

    Hello,你好呀,我是大白(●-●) 菜单 lambda表达式 函数式接口 lambda表达式 lambda表达式可以看成匿名内部类的一个简洁写法 在语法上,Lambda表达式包含三个部分: 参数列 ...

  6. jdk8新特性:Lambda表达式简单测试

    import java.awt.event.ActionEvent; import java.awt.event.ActionListener;import javax.swing.JButton; ...

  7. java x=8_Java8新特性之lambda表达式

    简介 Java8带来的新特性之一Lambda表达式,又称之为函数式编程,核心思想是将面向对象中的传递对象变为传递行为 语法 expression = (variable) -> anction ...

  8. java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合

    java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合 比如,我有一张表: entity Category.java service CategoryServic ...

  9. 【java8新特性】——lambda表达式与函数式接口详解(一)

    一.简介 java8于2014年发布,相比于java7,java8新增了非常多的特性,如lambda表达式.函数式接口.方法引用.默认方法.新工具(编译工具).Stream API.Date Time ...

  10. java8新特性之lambda表达式--超级详细版本

    java8新特性之lambda表达式 1.什么是lambda表达式?为什么用它? 2. 为什么Java需要lambda表达式? 3. lambda表达式的语法 4.函数式接口 4.1 什么是函数式接口 ...

最新文章

  1. 2020年ACM团队新生第一次周赛题解
  2. lay和lied_lie和lay的区别和用法是什么
  3. SSM框架的搭建(idea)
  4. 使用文本挖掘实现站点个性化推荐
  5. PHP中文乱码的常见解决方法总结
  6. Java01-day01【发展史、跨平台原理、JRE和JDK、常用DOS命令、关键字、常量、数据类型、变量使用的注意事项、标识符、类型转换】
  7. java map 输入 查询 修改_map的查询和修改方法
  8. linux内核测试,Linux内核测试的生命周期
  9. 海龟画图 python太阳花_python 简单的绘图工具turtle使用详解
  10. [转]面向对象的三个基本特征
  11. ios 中的tintColor
  12. Android Studio新建项目出错如何解决
  13. 浅谈JavaScript代码预解析 + 示例详解
  14. 如何通过QQ机器人技术实现禅道bug的自动提交功能
  15. [深度学习] ImageAI库使用笔记
  16. 利用JAVA流处理-统计男员工人数;找出所有薪资大于 5000 元的女员工;找出大于平均年龄的员工
  17. 如何在Windows命令行(DOS界面)中调用 编译器 来编译C/C++源程序
  18. Mac上的远程连接工具Royal TSX,比FinalShell更值得被推荐
  19. 因微信网页授权调整解决方案
  20. 学术诚信的重要性_宋瑞:坚持学术诚信 恪守学术道德 捍卫学术尊严

热门文章

  1. win10两个磁盘合并成一个?win10系统怎么合并磁盘
  2. 1000个瓶子和10只老鼠问题浅解
  3. 如何在linux服务器下载文件夹,linux服务器怎么下载文件到本地
  4. lol国服维护可以玩别的服务器吗,LOL:除了艾欧尼亚,其他服务器都只能算是“郊区”吗?...
  5. [c++]一个简单的NEAT机器学习寻路实验
  6. “人机大战”简单复盘
  7. Windows 搜索
  8. 面向大规模流量活动的高可用架构实践
  9. Keras之TCN:基于keras框架利用时间卷积网络TCN算法对上海最高气温实现回归预测(把时间序列数据集转化为有监督学习数据集)案例
  10. 如何着手写一篇医学综述?