Java8 新特性1—— Lambda表达式、内置函数式接口、方法引用与构造器引用
lambda 表达式
Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)
基本语法: (parameters) -> expression
或 (parameters) ->{ statements; }
,由 参数域,"->",实现方法 三部分组成。
注意事项:
- 当参数为空时,参数域由 ()表示即可,多个参数时,参数之间用逗号","分隔;
- 参数不要求指定变量类型,编译器会根据代码上下文推断自动鉴别;
- 当实现方法只有一条语句时,{}可省略,当方法无返回值时,return 关键字可省略;
使用条件:
lambda 表达式主要用来实现行内执行的函数式接口;
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,并且接口需要用_@FunctionalInterface_ 注解修饰,例如:
@FunctionalInterface interface GreetingService { void sayMessage(String message); }
在Java8之前,一般用匿名内部类的方式来实现接口内的抽象方法,Java8可以使用lambda表达式来实现,以精简代码;
核心函数式接口
由于lambda表达式是来实现函数式接口的,所以使用之前需要先定义对应的函数式接口,大量使用会导致代码文件琐碎繁复,因此Java8针对常见的使用的场景,已经内置了大部分函数式接口,只有少部分需要我们自己单独定义;
Java内置了四大核心函数式接口
函数式接口 | 类型参数 | 返回类型 | 用途 |
---|---|---|---|
Consumer 消费型接口 |
T | void | 对类型为T的对象应用操作, 包含方法:void accept(T t); |
Supplier 供给型接口 |
无 | T | 返回类型为T的对象, 包含方法:T get(); |
Funtional<T,R> 函数型接口 |
T | R | 对类型为T的对象应用操作,并返回结果是R类型的对象, 包含方法:R apply(T,t); |
Predicate 断言型接口 |
T | boolean | 确定类型为T的对象是否满足某种约束,并返回boolean值, 包含方法:boolean test(T,t); |
其他接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
BiFunction<T, U, R> | T, U | R | 对类型为 T, U 参数应用操作,返回 R 类型的结果。 包含方法为R apply(T t, U u); |
UnaryOperator (Function子接口) |
T | T | 对类型为T的对象进行一元运算,并返回T类型的结果。 包含方法为T apply(T t); |
BinaryOperator (BiFunction 子接口) |
T, T | T | 对类型为T的对象进行二元运算,并返回T类型的结果。 包含方法为: T apply(T t1, T t2); |
BiConsumer<T, U> | T, U | void | 对 类 型 为 T, U 参数 应 用操作。 包含方法为void accept(T t, U u) |
ToIntFunction ToLongFunction ToDoubleFunction |
T | int long double |
分 别 计 算 int 、 long 、double、值的函数 |
IntFunction LongFunction DoubleFunction |
int long double |
R | 参 数 分 别 为 int 、 long 、double 类型的函数 |
结合lambda表达式和内置函数式接口的代码示例
public void checkSalary(List<Employee> employees, Predicate<Employee> p){ for(Employee employee:employees){ if (p.test(employee)) { System.out.println(employee.getName()); } } } @Test public void testLambda(){ List<Employee> employeeList = Arrays.asList( new Employee("张三",2500,34), new Employee("李四",4500,45), new Employee("lisi",3500,35), new Employee("zhangsan",3000,30)); // 筛选出所有薪水在3000元以上的员工姓名 checkSalary(employeeList,(e)->e.getSalary()>3000); }
方法引用与构造器引用
方法引用
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!(实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!)方法引用:使用操作符 “::” 将方法名和对象或类的名字分隔开来。
如下三种主要使用情况 :
- 对象::实例方法
- 类::静态方法
- 类::实例方法
//例如 (x) -> System.out.println(x); //等同于 System.out::println //例如 BinaryOperator<Double> bo = (x,y) -> Math.pow(x,y); //等同于 BinaryOperator<Double> bo = Math::pow; //例如 compare((x,y) -> x.equals(y), "abcdef","abcdef"); //等同于 compare(String::equals,"abc","abc");
注意:当需要引用方法的第一个参数是调用对象,并且第二个参数是需要引用方法的第二个参数(或无参数)时:ClassName::methodName
构造器引用
格式:ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一致
数组引用
格式: type[] :: new
// 例如: Function<Integer,Integer[]> fun = (n) -> new Integer[n]; // 等同于: Function<Integer,Integer[]> fun = Integer[]::new;
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· C# 13 中的新增功能实操
· Vue3封装支持Base64导出的电子签名组件
· 万字长文详解Text-to-SQL
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)