Java Lambda表达式超详细入门教程(作用、定义、函数式接口、内置接口、方法引用实战)
博客简介:Java8重磅新特性Lambda表达式,简化匿名内部类写法,适配函数式编程思想。本文从零讲解Lambda作用、语法定义、函数式接口核心概念、四大预定义函数式接口,附带双冒号方法引用完整案例,零基础也能看懂上手,同时梳理日常开发常见易错问题。
一、Lambda表达式初始作用
在Java8之前,我们使用匿名内部类实现简易功能、线程创建、集合遍历、回调逻辑时,代码冗余度极高。
大量格式固定、仅有业务逻辑不同的模板代码,挤占核心业务可读性。
Lambda表达式核心作用:
简化匿名内部类繁琐写法,去掉重复格式代码
支持函数式编程,把函数当作参数传递
精简线程、集合遍历、条件筛选、回调等常用场景代码
配合Stream流使用,极大提升集合操作简洁度
无Lambda旧写法痛点示例
// 开启线程,匿名内部类模板代码繁杂,核心逻辑被掩盖
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("传统线程执行");
}
}).start();
Lambda简化后
// 仅保留核心执行逻辑,代码精简直观
new Thread(() -> System.out.println("Lambda线程执行")).start();
二、Lambda表达式标准定义与语法
1. 语法格式
(参数列表) -> {方法体代码}
2. 各部分含义
(参数列表):对应抽象方法的形参,可省略数据类型
->:Lambda专属连接符号,分隔参数与方法体
{方法体}:重写方法的具体业务逻辑
3. 语法省略规则(常用简写)
参数只有一个:小括号可以省略
方法体只有一行代码:大括号、return关键字均可省略
无参数:必须保留空小括号()
4. 完整基础示例
// 1.无参数无返回值函数式接口
interface NoParam{
void show();
}
// 无参写法,括号不可省略
NoParam no1 = () -> System.out.println("无参数Lambda");
// 2.单个参数简写形式
interface OneParam{
void say(String msg);
}
// 单个参数省去外层小括号
OneParam one = msg -> System.out.println(msg);
// 3.带返回值单行简写,自动省略return与大括号
interface ReturnFunc{
int getSum(int a,int b);
}
ReturnFunc sum = (a,b) -> a + b;
三、函数式接口(Lambda使用前提)
1. 定义
函数式接口:有且仅有一个抽象方法的接口,专门供Lambda表达式使用。
2. 核心注解 @FunctionalInterface
该注解强制校验接口规范:
只能存在一个抽象方法
包含默认方法、静态方法不影响接口判定
不符合规范编译直接报错,避免书写错误
3. 自定义函数式接口示例
// 声明为函数式接口,编译自动校验格式
@FunctionalInterface
public interface MyFunction {
// 唯一抽象方法
void handle(String content);
}
4. Lambda使用函数式接口
public class TestFuncInterface {
public static void main(String[] args) {
// Lambda表达式直接赋值给函数式接口引用
MyFunction func = str -> System.out.println("处理内容:" + str);
// 调用抽象方法执行逻辑
func.handle("自定义函数式接口测试");
}
}
四、四大预定义函数式接口
Java8内置通用函数式接口,日常开发无需自定义接口,直接拿来使用,覆盖无参、有参、无返回、有返回所有场景。
接口名抽象方法作用场景Consumer<T>void accept(T t)消费型:有参数,无返回值Supplier<T>T get()供给型:无参数,有返回值Function<T,R>R apply(T t)函数型:有参数,有返回值,类型转换Predicate<T>boolean test(T t)判断型:有参数,返回布尔值,条件筛选1. Consumer 消费型接口
接收数据,处理不返回
// 消费数据,对传入字符串做打印处理
Consumer<String> consumer = s -> System.out.println("消费数据:"+s);
consumer.accept("测试消费接口");
2. Supplier 供给型接口
无参,对外返回数据
// 对外提供指定数值数据
Supplier<Integer> supplier = () -> 666;
System.out.println(supplier.get());
3. Function 函数型接口
参数转成指定类型返回
// 将字符串转为对应长度数值,类型转换处理
Function<String,Integer> func = s -> s.length();
System.out.println(func.apply("Lambda测试"));
4. Predicate 判断型接口
条件判断,返回布尔结果
// 数值条件校验,判断是否大于10
Predicate<Integer> predicate = num -> num > 10;
System.out.println(predicate.test(15));
五、双冒号 :: 方法引用(Lambda进阶简写)
1. 概念
方法引用::是Lambda表达式的进一步简化,当Lambda方法体只调用已有现成方法,即可使用双冒号替代Lambda写法,代码更精简,可读性更强。
2. 四种使用格式与实战案例
格式1:对象::实例方法
String str = "方法引用测试";
// 调用已有实例的成员方法
Supplier<String> sup = str::toUpperCase;
System.out.println(sup.get());
格式2:类名::静态方法
// 调用类的静态工具方法
Function<Integer,Integer> fun = Math::abs;
System.out.println(fun.apply(-99));
格式3:类名::实例方法
// 通过类名调用通用实例方法
Predicate<String> pre = String::isEmpty;
System.out.println(pre.test(""));
格式4:类名::new 构造方法引用
// 引用构造方法,实例化对象
Supplier<Person> personSup = Person::new;
Person p = personSup.get();
3. 完整综合测试类
// 实体测试类
class Person{
public Person(){}
}
public class MethodRefTest {
public static void main(String[] args) {
// 对象::实例方法调用
String msg = "java lambda";
Consumer<String> con = msg::concat;
con.accept(" 方法引用");
// 类::静态方法调用
Function<Integer,Integer> absFunc = Math::abs;
System.out.println(absFunc.apply(-20));
}
}
六、Lambda综合实战小案例
结合函数式接口、方法引用完成集合筛选
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* Lambda结合Stream流实现集合过滤实操
*/
public class LambdaDemo {
public static void main(String[] args) {
// 初始化字符串集合
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Lambda");
list.add("CSDN博客");
// Lambda表达式筛选长度大于3的字符串
List<String> res = list.stream()
.filter(s -> s.length()>3)
.collect(Collectors.toList());
// 输出筛选结果
System.out.println(res);
}
}
七、常见易错点汇总
使用前提限制
Lambda不能独立运行,必须依附仅有单个抽象方法的函数式接口,普通接口、抽象类无法使用Lambda表达式赋值。
语法简写边界
多行代码必须保留大括号,有返回值多行语句必须手动书写return关键字,不可省略。
变量引用规范
Lambda内部引用局部变量时,变量默认隐式final修饰,不允许二次修改赋值。
方法引用匹配要求
引用的方法参数列表、返回值类型,必须和函数式接口抽象方法格式保持一致,否则编译报错。
访问权限问题
无法直接访问接口私有方法,仅可调用公共、默认、静态方法。
八、总结
1.Lambda核心:简化匿名内部类,必须依托函数式接口使用
2.语法:(参数)->{方法体},支持多种简写规则,牢记简写边界
3.函数式接口:仅一个抽象方法,@FunctionalInterface校验规范
4.四大内置接口覆盖绝大多数业务场景,减少自定义接口开发成本
5.双冒号方法引用是Lambda极致简写,调用已有方法时优先使用
6.Lambda搭配Stream流,集合遍历、筛选、排序效率大幅提升
7.开发中规避变量修改、格式不匹配等易错点,写出规范简洁代码
