当前位置: 首页 > news >正文

【JDK1.8 新特性】Lambda表达式

1. 什么是Lambda表达式?

Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

2. 什么是函数式接口?为什么需要函数式接口?

  • 只包含一个抽象方法(Single Abstract Method,简称SAM)的接口,称为函数式接口。当然该接口可以包含其他非抽象方法。
  • 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式抛出一个受检异常(即:非运行时异常),那么该异常需要在目标接口的抽象方法上进行声明)。
  • 我们可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口。同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。
  • java.util.function包下定义了Java 8 的丰富的函数式接口

3. Lambda表达式本质

Java中Lambda表达式其实就是创建实例对象的另一种方式,但是它比较特殊,比较简洁,并且创建的是一个匿名对象(万物皆对象!)。

从下边示例代码可以看出,Lambda表达式只是对抽象方法进行了重写,具体的输入是由最终的调用者决定的。只要输入相同,输出就一定相同。

函数式接口:

@FunctionInterface //声明该接口为函数式接口
public interface FunctionInterfaceTest<T>{...void method(T t); // 只能有一个抽象方法
}

Lambda表达式:

// 左边是接口,右边是对抽象方法的重写
FunctionInterfaceTest m = (t)-> System.out.println(t);// 调用
m.method(11); //输出11

4. 如何理解函数式接口?

Java从诞生日起就是一直倡导“一切皆对象”,在Java里面面向对象(OOP)编程是一切。但是随着python、scala等语言的兴起和新技术的挑战,Java不得不做出调整以便支持更加广泛的技术要求,即Java不但可以支持OOP还可以支持OOF(面向函数编程)

  • Java8引入了Lambda表达式之后,Java也开始支持函数式编程。
  • Lambda表达式不是Java最早使用的。目前C++,C#,Python,Scala等均支持Lambda表达式。

面向对象思想:

  • 做一件事情,找到一个能解决这件事情去的对象,调用对象的方法,完成事情。

函数式编程思想:

  • 只要能获得结果,谁去做的、怎么做的都不重要,重视的是结果,不是过程。

在函数式编程语言当中,函数被当做一等公民对待。在将函数作为一等公民的编程语言中,Lambda表达式的类型是函数。但是在Java8中,有所不同。在Java8中,Lambda表达式是对象,而不是函数,它们必须依附于一类特别的对象类型——函数式接口。

简单的说,在Java8中,Lambda表达式就是一个函数式接口的实例。这就是Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示。

5. 语法格式

接口<泛型> 引用 = (形参列表) -> { 方法体 }

  • 引用左边是接口,引用右边的Lambda是对接口中抽象方法的重写
  • ->的左边:Lambda形参列表,对应抽象方法的形参列表
  • ->的右边:Lambda体,对应重写的抽象方法的方法体

调用:引用.抽象方法(实参);,这里调用的是被重写的抽象方法。

因为Lambda表达式是对抽象方法的重写,因而一定要要先了解被重写的抽象方法是如何定义的。

语法格式一:无参,无返回值

@Test
public void test1(){//未使用Lambda表达式Runnable r1 = new Runnable() {@Overridepublic void run() {System.out.println("我爱北京天安门");}};r1.run();System.out.println("***********************");//使用Lambda表达式Runnable r2 = () -> {System.out.println("我爱北京故宫");};r2.run();
}

语法格式二:Lambda 需要一个参数,但是没有返回值。

@Test
public void test2(){//未使用Lambda表达式Consumer<String> con = new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}};con.accept("谎言和誓言的区别是什么?");System.out.println("*******************");//使用Lambda表达式Consumer<String> con1 = (String s) -> {System.out.println(s);};con1.accept("一个是听得人当真了,一个是说的人当真了");}

语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”

Lambda 表达式中的参数类型都是由编译器推断得出的。Lambda 表达式中无需指定类型,程序依然可以编译,这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。这就是所谓的“类型推断”。

@Test
public void test3(){//语法格式三使用前Consumer<String> con1 = (String s) -> {System.out.println(s);};con1.accept("一个是听得人当真了,一个是说的人当真了");System.out.println("*******************");//语法格式三使用后,形参类型可由接口泛型 推断出来Consumer<String> con2 = (s) -> {System.out.println(s);};con2.accept("一个是听得人当真了,一个是说的人当真了");}

语法格式四:Lambda 若只需要一个参数时,参数的小括号可以省略

@Test
public void test4(){//语法格式四使用前Consumer<String> con1 = (s) -> {System.out.println(s);};con1.accept("一个是听得人当真了,一个是说的人当真了");System.out.println("*******************");//语法格式四使用后Consumer<String> con2 = s -> {System.out.println(s);};con2.accept("一个是听得人当真了,一个是说的人当真了");}

语法格式五:Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值

@Test
public void test5(){//语法格式五使用前Comparator<Integer> com1 = new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {System.out.println(o1);System.out.println(o2);return o1.compareTo(o2);}};System.out.println(com1.compare(12,21));System.out.println("*****************************");//语法格式五使用后Comparator<Integer> com2 = (o1,o2) -> {System.out.println(o1);System.out.println(o2);return o1.compareTo(o2);};System.out.println(com2.compare(12,6));}

语法格式六:当 Lambda 体只有一条语句时,return 与大括号若有,都可以省略

@Test
public void test6(){//语法格式六使用前Comparator<Integer> com1 = (o1,o2) -> {return o1.compareTo(o2);};System.out.println(com1.compare(12,6));System.out.println("*****************************");//语法格式六使用后Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);System.out.println(com2.compare(12,21));}@Test
public void test7(){//语法格式六使用前Consumer<String> con1 = s -> {System.out.println(s);};con1.accept("一个是听得人当真了,一个是说的人当真了");System.out.println("*****************************");//语法格式六使用后Consumer<String> con2 = s -> System.out.println(s);con2.accept("一个是听得人当真了,一个是说的人当真了");}

6. Java内置的四大核心函数式接口

接口功能类型接口抽象方法描述
消费型接口Consumervoid accept(T t)负责逻辑处理,没有返回值
供给型接口SupplierT get()不需要参数,有返回值
函数型接口Function<T,R>R apply(T t)接收一个参数,并返回指定类型数据
判断型接口Predicateboolean test(T t)接收一个参数,返回布尔值
http://www.lryc.cn/news/32748.html

相关文章:

  • 【Vue.js】Vuex核心概念
  • react router零基础使用教程
  • IOC三种依赖注入的方式,以及区别
  • Ubuntu18安装新版本PCL-1.13,并和ROS自带PCL-1.8共存
  • 计算机图形学08:中点BH算法绘制抛物线(100x = y^2)
  • 基于java的高校辅导员工作管理系统
  • 字节3次都没裁掉的7年老测试。掌握设计业务与技术方案,打开上升通道!
  • 详细介绍关于链表【数据结构】
  • 2.3 二分搜索技术
  • RWEQ模型的土壤风蚀模数估算、其变化归因分析
  • 学习streamlit-1
  • GPS定位知识介绍
  • 【Linux】理解Linux环境变量
  • ISCSI块存储-集群
  • 11.Maxwell 部署
  • 一文速学-GBDT模型算法原理以及实现+Python项目实战
  • 前端——2.HTML基本结构标签
  • OAK深度相机使用不同镜头和本地视频流进行模型推理
  • [项目] Boost搜索引擎
  • 解决新版QGIS找不到Georeferencer插件
  • c---冒泡排序模拟qsort
  • Java知识复习(十四)JS
  • 代码随想录刷题-数组-移除元素
  • 聚观早报 |拼多多跨境电商业务正式登陆澳洲;中国加快6G网络研发
  • MDK Keil5 创建Stm32工程-理论篇(这里以Stm32F103Zet6为例)
  • 应届大学生学什么技术好?哪些技术适合年轻人?
  • 车企数据分类分级的实践指南出炉!“数据安全推进计划”发布,奇点云参编
  • Nginx学习 (2) —— 虚拟主机配置
  • Java 动态代理简述和实例
  • Unity编译器扩展(Advanced Editor Scripting)