Lambda表达式
Lambda 表达式,也可称为闭包,它是 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中),允许用表达式代替功能性接口。使用 Lambda 表达式可以使代码变的更加简洁紧凑,但是随之而来的是代码可读性变差。
语法
java
(parameters) -> expression
或
(parameters) ->{ statements; }
-
parameters
是参数列表, -
expression
或{ statements; }
是Lambda 表达式的主体。
案例
在匿名内部类上面使用 Lambda,效果更加明显
java
// 传统的匿名内部类
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello World!");
}
};
// 使用 Lambda 表达式
Runnable runnable2 = () -> System.out.println("Hello World!");
函数式接口介绍
一个接口只有一个抽象方法的接口叫做函数式接口

基本使用
- 如果只有一个参数,可以省略括号;
- 如果没有参数,也需要空括号。
- 只有一行语句,可以省略大括号
- 无参,无返回值,只有一行语句(多行语句时大括号不能省略)
java
public class Main {
public static void main(String[] args) {
Inter inter = () -> System.out.println("Hello");
inter.test();
}
}
interface Inter {
void test();
}
- 有一个参数,无返回值,只有一行语句(多行语句时大括号不能省略)
java
public class Main {
public static void main(String[] args) {
//参数类型可以不用写,会自动推测
Inter inter = str -> System.out.println(str);
inter.test("Hello");
}
}
interface Inter {
void test(String str);
}
- 有一个参数,有返回值,只有一行语句(多行语句时大括号不能省略)
java
public class Main {
public static void main(String[] args) {
//参数类型可以不用写,会自动推测
Inter inter = str -> str;
inter.test("Hello");
}
}
interface Inter {
String test(String str);
}
内置的函数式接口
上面我们介绍的 Lambda 的基本使用, 我们每次要使用某种类型的函数式接口都要自己先创建一个函数式接口,比较繁琐,所以在 JDK8 之后,就内置了 4 个核心的函数式接口供我们使用。
简单介绍
核心函数式接口
接口 | 特点 | 抽象方法 |
---|---|---|
Consumer< T > | 有参,无返回值 | accept(T t) |
Supplier< T > | 无参,有返回值 | get() |
Function< T, R > | 有参,有返回值 | apply(T t) |
Predicate< T > | 有参有返回值,返回 Boolean 类型 | test(T t) |
其他函数式接口
对于这些函数式接口,其实就是对核心的函数式接口做了扩展,不如参数数量增加等等
接口 | 特点 | 抽象方法 |
---|---|---|
BiConsumer< T, U > | 接收两个不同类型的参数,无返回值 | accept(T t, U u) |
BiFunction< T, U ,R > | 接收两个不同类型的参数,返回一个结果 | R apply(T t, U u) |
UnaryOperator< T > | 输入和输出类型相同 | T apply(T t) |
BinaryOperator | 对两个同类型操作数进行运算,返回同类型结果 | T apply(T t,T t) |
详细介绍(核心函数式接口)
Consumer<T>
:消费型接口
- 抽象方法 :
void accept(T t)
- 用途:接收一个参数并执行操作,无返回值
基本使用
java
public static void main(String[] args) {
// 使用 lambda 表达式实现 Consumer
Consumer<String> printer = (str) -> System.out.println(str);
// 调用 accept 方法
printer.accept("Hello");
}
遍历集合
java
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 使用 Consumer 遍历集合,forEach 的参数就是一个 Consumer 接口
names.forEach(name -> System.out.println("Hello, " + name));
}
Supplier<T>
:供给型接口
- 抽象方法 :
T get()
- 用途:不接收参数,返回一个值
基本使用
java
public static void main(String[] args) {
// 使用 lambda 表达式实现 Supplier
Supplier<Double> randomSupplier = () -> Math.random();
// 调用 get 方法获取值
System.out.println(randomSupplier.get());
}
Function<T,R>
:函数型接口
- 抽象方法 :
R apply(T t)
- 用途:接收一个参数,返回一个结果
基本使用
java
public static void main(String[] args) {
// 将字符串转换为整数
// 使用 lambda 表达式实现 Function
Function<String, Integer> stringToInt = str -> Integer.parseInt(str);
// 调用 apply 方法
Integer result = stringToInt.apply("123");
}
Predicate<T>
:断言型接口
- 抽象方法 :
boolean test(T t)
- 用途:接收一个参数,返回布尔值
基本使用
java
public static void main(String[] args) {
// 判断字符串长度是否大于 5
Predicate<String> lengthChecker = str -> str.length() > 5;
// 调用 test 方法
System.out.println(lengthChecker.test("HelloWorld")); // 输出: true
System.out.println(lengthChecker.test("Hi")); // 输出: false
}
方法引用
介绍
在Java中,方法引用是一种强大的功能,它允许您在Lambda表达式中引用方法,而不是在表达式中直接定义这些方法。方法引用使代码更加简洁和可读,尤其在函数式编程中非常有用。
使用前提
如果 Lambda 表达式体中的方法已经被实现过了,就可以使用方法引用,Lambda 表达式引用的方法的参数列表和返回值要和函数式接口的中定义的抽象方法参数列表和返回值一致
语法格式
- 静态方法引用:类名::静态方法名
- 实例方法引用:实例对象名::实例方法名
- 特殊方法引用:类名::实例方法名
- 构造方法引用:类名::new
静态方法引用
没使用静态方法引用
java
public class Main {
public static void main(String[] args) {
Consumer<String> consumer = s -> Test.test(s);
consumer.accept("Hello");
}
}
class Test {
public static void test(String str) {
System.out.println(str);
}
}
使用静态方法引用
java
public class Main {
public static void main(String[] args) {
Consumer<String> consumer = Test::test;
consumer.accept("Hello");
}
}
class Test {
//静态方法
public static void test(String str) {
System.out.println(str);
}
}
实例方法引用
- 引用前

- 引用后

- 对于集合遍历也可以使用到该方式

特殊方法引用
当我们函数有参数的时候,且第一个参数调用方法,则可以使用特殊方法引用
- 使用前

- 使用后

构造方法引用
-
使用前
-
使用后

数组构造引用

super 和 this 引用
主要用于在一个方法中的函数接口调用了,父类的某个方法或者本类的某个方法
